home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / TEECHART / Src Code / CHART.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-10-24  |  76.8 KB  |  2,754 lines

  1. {******************************************}
  2. {   TCustomChart & TChart Components       }
  3. { Copyright (c) 1995-1998 by David Berneda }
  4. {    All Rights Reserved                   }
  5. {******************************************}
  6. {$R-,S-,Q-,I-,A+,U-,X+,B-,W-,P-,V-}
  7. {$I teedefs.inc}
  8. unit Chart;
  9.  
  10. interface
  11.  
  12. uses Classes, Messages, WinTypes, WinProcs, SysUtils, Graphics,
  13.      TeEngine, Printers, Controls, ExtCtrls, TeeProcs, TeeFunci, Forms,
  14.      TeCanvas
  15.      {$IFDEF D1}
  16.      ,Menus
  17.      {$ENDIF}
  18.      ;
  19.  
  20. Const
  21.      TeeMsg_DefaultFunctionName = 'TeeFunction'; { <-- dont translate }
  22.      TeeMsg_DefaultSeriesName   = 'Series';      { <-- dont translate }
  23.      ChartComponentPalette      = 'TeeChart';    { <-- dont translate }
  24.  
  25.  
  26. Var  AnimatedZoomFactor   : Double;
  27.      TeeZoomMouseButton   : TMouseButton; { button used to zoom }
  28.      TeeScrollMouseButton : TMouseButton; { button used to scroll }
  29.      TeeZoomKeyShift      : TShiftState;  { keys that should be pressed to start zoom }
  30.      TeeScrollKeyShift    : TShiftState;  { keys that should be pressed to start scroll }
  31.  
  32. Type
  33.   TeeString        = Array[0..255] of char;
  34.   TeeGalleryString = String[20];
  35.  
  36.   TCustomChart=class;
  37.  
  38.   TChartWall=class(TPersistent)
  39.   private
  40.     FColor       : TColor;
  41.     FBrush       : TChartBrush;
  42.     FDark3D      : Boolean;
  43.     FPen         : TChartPen;
  44.     FSize        : Longint;
  45.     FParentChart : TCustomChart;
  46.     Procedure SetBrush(Value:TChartBrush);
  47.     Procedure SetColor(Value:TColor);
  48.     Procedure SetDark3D(Value:Boolean);
  49.     Procedure SetPen(Value:TChartPen);
  50.     Procedure SetSize(Value:Longint);
  51.     Function IsColorStored:Boolean;
  52.     Function ApplyDark3D:Boolean;
  53.   protected
  54.     DefaultColor:TColor;
  55.   public
  56.     Constructor Create(AOwner:TCustomChart);
  57.     Destructor Destroy; override;
  58.     Procedure Assign(Source:TPersistent); override;
  59.     property ParentChart:TCustomChart read FParentChart;
  60.   published
  61.     property Brush:TChartBrush read FBrush write SetBrush;
  62.     property Color:TColor read FColor write SetColor stored IsColorStored;
  63.     property Dark3D:Boolean read FDark3D write SetDark3D default True;
  64.     property Pen:TChartPen read FPen write SetPen;
  65.     property Size:Longint read FSize write SetSize default 0;
  66.   end;
  67.  
  68.  { TCustomChartLegend Component }
  69.  
  70.   TLegendStyle    =(lsAuto,lsSeries,lsValues,lsLastValues);
  71.   TLegendAlignment=(laLeft,laRight,laTop,laBottom);
  72.   LegendException =class(Exception);
  73.  
  74.   TOnGetLegendText=Procedure( Sender:TCustomAxisPanel;
  75.                   LegendStyle:TLegendStyle;
  76.                   Index:Longint;
  77.                   Var LegendText:String) of Object;
  78.  
  79.   TCustomChartLegend=class(TChartFontObject)
  80.   private
  81.     FAlignment     : TLegendAlignment;
  82.     FBrush         : TChartBrush;
  83.     FColor         : TColor;
  84.     FColorWidth    : Integer;
  85.     FDividingLines : TChartHiddenPen;
  86.     FFirstValue    : Longint;
  87.     FFrame         : TChartPen;
  88.     FHorizMargin   : Integer;
  89.     FInverted      : Boolean;
  90.     FLegendStyle   : TLegendStyle;
  91.     FMaxNumRows    : Integer;
  92.     FRectLegend    : TRect;
  93.     FResizeChart   : Boolean;
  94.     FShadowColor   : TColor;
  95.     FShadowSize    : Integer;
  96.     FTextStyle     : TLegendTextStyle;
  97.     FTopLeftPos    : Integer;
  98.     FVertMargin    : Integer;
  99.     FVisible       : Boolean;
  100.     { Internal }
  101.     IColorWidth    : Longint;
  102.     ILegendStyle   : TLegendStyle;
  103.     procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED;
  104.     procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  105.     Function GetParentChart:TCustomChart;
  106.     Function GetVertical:Boolean;
  107.     Procedure SetAlignment(Value:TLegendAlignment);
  108.     Procedure SetBrush(Value:TChartBrush);
  109.     Procedure SetColor(Value:TColor);
  110.     Procedure SetColorWidth(Value:Integer);
  111.     Procedure SetDividingLines(Value:TChartHiddenPen);
  112.     Procedure SetFirstValue(Value:Longint);
  113.     Procedure SetFrame(Value:TChartPen);
  114.     Procedure SetHorizMargin(Value:Integer);
  115.     Procedure SetInverted(Value:Boolean);
  116.     Procedure SetLegendStyle(Value:TLegendStyle);
  117.     Procedure SetMaxNumRows(Value:Integer);
  118.     Procedure SetResizeChart(Value:Boolean);
  119.     Procedure SetShadowColor(Value:TColor);
  120.     Procedure SetShadowSize(Value:Integer);
  121.     Procedure SetTextStyle(Value:TLegendTextStyle);
  122.     Procedure SetTopLeftPos(Value:Integer);
  123.     Procedure SetVertMargin(Value:Integer);
  124.     Procedure SetVisible(Value:Boolean);
  125.   protected
  126.     Procedure CalcLegendStyle;
  127.     property InternalLegendStyle:TLegendStyle read ILegendStyle;
  128.     Function MaxLegendValues(YLegend,ItemHeight:Longint):Longint; virtual;
  129.   public
  130.     NumCols      : Longint;
  131.     NumRows      : Longint;
  132.  
  133.     Constructor Create(AOwner:TCustomChart);
  134.     Destructor Destroy; override;
  135.     Procedure Assign(Source:TPersistent); override;
  136.     Function FormattedValue(ASeries:TChartSeries; ValueIndex:Longint):String;
  137.     Function FormattedLegend(SeriesOrValueIndex:Longint):String;
  138.     property ParentChart:TCustomChart read GetParentChart;
  139.     Procedure Draw; virtual;
  140.     Function GetColorRect(X1,Y0,Y1:Longint):TRect;
  141.     Function TotalLegendItems:Longint;
  142.     Function MaxLegendWidth(NumLegendValues:Longint):Longint;
  143.     Function Clicked(x,y:Integer):Integer;
  144.     { public property }
  145.     property RectLegend : TRect read FRectLegend write FRectLegend;
  146.     { to be published }
  147.     property Alignment:TLegendAlignment read FAlignment write SetAlignment
  148.                     default laRight;
  149.     property Brush:TChartBrush read FBrush write SetBrush;
  150.     property Color:TColor read FColor write SetColor default clWhite;
  151.     property ColorWidth:Integer read FColorWidth write SetColorWidth default 12;
  152.     property DividingLines:TChartHiddenPen read FDividingLines write SetDividingLines;
  153.     property FirstValue:Longint read FFirstValue write SetFirstValue default 0;
  154.     property Font;
  155.     property Frame:TChartPen read FFrame write SetFrame;
  156.     property HorizMargin:Integer read FHorizMargin write SetHorizMargin default 0;
  157.     property Inverted:Boolean read FInverted write SetInverted default False;
  158.     property LegendStyle:TLegendStyle read FLegendStyle
  159.                       write SetLegendStyle default lsAuto;
  160.     property MaxNumRows:Integer read FMaxNumRows write SetMaxNumRows default 10;
  161.     property ResizeChart:Boolean read FResizeChart write SetResizeChart default True;
  162.     property ShadowColor:TColor read FShadowColor write SetShadowColor default clBlack;
  163.     property ShadowSize:Integer read FShadowSize write SetShadowSize default 3;
  164.     property TextStyle:TLegendTextStyle read FTextStyle
  165.                     write SetTextStyle default ltsLeftValue;
  166.     property TopPos:Integer read FTopLeftPos write SetTopLeftPos default 10;
  167.     property Vertical:Boolean read GetVertical;
  168.     property VertMargin:Integer read FVertMargin write SetVertMargin default 0;
  169.     property Visible:Boolean read FVisible write SetVisible default True;
  170.   end;
  171.  
  172.   TChartLegend=class(TCustomChartLegend)
  173.   published
  174.     property Alignment;
  175.     property Brush;
  176.     property Color;
  177.     property ColorWidth;
  178.     property DividingLines;
  179.     property FirstValue;
  180.     property Font;
  181.     property Frame;
  182.     property HorizMargin;
  183.     property Inverted;
  184.     property LegendStyle;
  185.     property MaxNumRows;
  186.     property ResizeChart;
  187.     property ShadowColor;
  188.     property ShadowSize;
  189.     property TextStyle;
  190.     property TopPos;
  191.     property VertMargin;
  192.     property Visible;
  193.   end;
  194.  
  195.   TChartTitle=class(TChartFontObject)
  196.   private
  197.     FAdjustFrame : Boolean;
  198.     FAlignment   : TAlignment;
  199.     FBrush       : TChartBrush;
  200.     FColor       : TColor;
  201.     FFrame       : TChartHiddenPen;
  202.     FText        : TStrings;
  203.     FTitleRect   : TRect;
  204.     FVisible     : Boolean;
  205.     Function IsFontStored:Boolean;
  206.     Procedure SetAdjustFrame(Value:Boolean);
  207.     Procedure SetAlignment(Value:TAlignment);
  208.     Procedure SetBrush(Value:TChartBrush);
  209.     Procedure SetColor(Value:TColor);
  210.     Procedure SetFrame(Value:TChartHiddenPen);
  211.     Procedure SetText(Value:TStrings);
  212.     Procedure SetVisible(Value:Boolean);
  213.   protected
  214.     DefaultFontColor : TColor;
  215.     DefaultFontStyle : TFontStyles;
  216.   public
  217.     Constructor Create(AOwner: TCustomChart);
  218.     Destructor Destroy; override;
  219.  
  220.     Procedure Assign(Source:TPersistent); override;
  221.     Function Clicked(x,y:Integer):Boolean;
  222.     procedure Draw(OnTop:Boolean);
  223.     property TitleRect:TRect read FTitleRect;
  224.   published
  225.     property AdjustFrame:Boolean read FAdjustFrame write SetAdjustFrame
  226.                  default True;
  227.     property Alignment: TAlignment read FAlignment
  228.                    write SetAlignment default taCenter;
  229.     property Brush:TChartBrush read FBrush write SetBrush;
  230.     property Color:TColor read FColor write SetColor default clTeeColor;
  231.     property Font:TFont read FFont write SetFont stored IsFontStored;
  232.     property Frame:TChartHiddenPen read FFrame write SetFrame;
  233.     property Text:TStrings read FText write SetText;
  234.     property Visible:Boolean read FVisible write SetVisible default True;
  235.   end;
  236.  
  237.   TChartClick=procedure( Sender:TCustomChart;
  238.              Button:TMouseButton;
  239.              Shift: TShiftState;
  240.              X, Y: Integer) of object;
  241.  
  242.   TChartClickAxis=procedure( Sender:TCustomChart;
  243.                  Axis:TChartAxis;
  244.                  Button:TMouseButton;
  245.                  Shift: TShiftState;
  246.                  X, Y: Integer) of object;
  247.  
  248.   TChartClickSeries=procedure( Sender:TCustomChart;
  249.                    Series:TChartSeries;
  250.                    ValueIndex:Longint;
  251.                    Button:TMouseButton;
  252.                    Shift: TShiftState;
  253.                    X, Y: Integer) of object;
  254.  
  255.   TOnGetLegendPos=Procedure( Sender:TCustomChart; Index:Longint;
  256.                  Var X,Y,XColor:Longint) of object;
  257.  
  258.   TOnGetLegendRect=Procedure( Sender:TCustomChart; Var Rect:TRect) of object;
  259.  
  260.   TChartAllowScrollEvent=Procedure( Sender:TChartAxis; Var AMin,AMax:Double;
  261.                     Var AllowScroll:Boolean ) of object;
  262.  
  263.   TAxisSavedScales=Record
  264.     Auto    : Boolean;
  265.     AutoMin : Boolean;
  266.     AutoMax : Boolean;
  267.     Min     : Double;
  268.     Max     : Double;
  269.   end;
  270.  
  271.   TAllAxisSavedScales=Record
  272.     Top    : TAxisSavedScales;
  273.     Left   : TAxisSavedScales;
  274.     Right  : TAxisSavedScales;
  275.     Bottom : TAxisSavedScales;
  276.   end;
  277.  
  278.   TCustomChart=class(TCustomAxisPanel)
  279.   private
  280.     FBackImageInside   : Boolean;
  281.     FBackWall          : TChartWall;
  282.     FBottomWall        : TChartWall;
  283.     FFoot              : TChartTitle;
  284.     FLeftWall          : TChartWall;
  285.     FLegend            : TChartLegend;
  286.     FRestoredAxisScales: Boolean;
  287.     FSavedScales       : TAllAxisSavedScales;
  288.     FTitle             : TChartTitle;
  289.  
  290.     { events }
  291.     FOnAllowScroll     : TChartAllowScrollEvent;
  292.     FOnClickAxis       : TChartClickAxis;
  293.     FOnClickBackGround : TChartClick;
  294.     FOnClickLegend     : TChartClick;
  295.     FOnClickSeries     : TChartClickSeries;
  296.     FOnGetLegendPos    : TOnGetLegendPos;
  297.     FOnGetLegendRect   : TOnGetLegendRect;
  298.     FOnGetLegendText   : TOnGetLegendText;
  299.     Function GetBackColor:TColor;
  300.     Function GetFrame:TChartPen;
  301.     Procedure RestoreScales(Const Saved:TAllAxisSavedScales);
  302.     Function SaveScales:TAllAxisSavedScales;
  303.     Procedure SetBackColor(Value:TColor);
  304.     procedure SetBackImageInside(Value:Boolean);
  305.     Procedure SetBackWall(Value:TChartWall);
  306.     Procedure SetBottomWall(Value:TChartWall);
  307.     Procedure SetFoot(Value:TChartTitle);
  308.     Procedure SetFrame(Value:TChartPen);
  309.     Procedure SetLeftWall(Value:TChartWall);
  310.     Procedure SetLegend(Value:TChartLegend);
  311.     Procedure SetTitle(Value:TChartTitle);
  312.   protected
  313.     Procedure CalcAxisRect; override;
  314.     Procedure CalcSeriesRect; override;
  315.     Function CalcWallSize(Axis:TCustomChartAxis):Longint; override;
  316.     Procedure CalcZoomPoints; virtual;
  317.     Procedure DoZoom(Const TopI,TopF,BotI,BotF,LefI,LefF,RigI,RigF:Double);
  318.     procedure DrawImage(Const R:TRect); override;
  319.     procedure DrawTitlesAndLegend; override;
  320.     Procedure DrawWalls; override;
  321.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  322.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  323.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  324.   public
  325.     Constructor Create(AOwner: TComponent); override;
  326.     Destructor Destroy; override;
  327.     Procedure Assign(Source:TPersistent); override;
  328.     Function AxisTitleOrName(Axis:TCustomChartAxis):String;
  329.     Procedure CalcClickedPart( Pos:TPoint; Var Part:TChartClickedPart );
  330.     Procedure ExchangeSeries(Series1,Series2:Longint);
  331.     Procedure FillSeriesSourceItems(ASeries:TChartSeries; Proc:TGetStrProc); virtual;
  332.     Procedure FillValueSourceItems(ValueList:TChartValueList; Proc:TGetStrProc); virtual;
  333.     Function GetASeries:TChartSeries; { return first active Series }
  334.     Function IsFreeSeriesColor(AColor:TColor; CheckBackground:Boolean):Boolean; override;
  335.     Procedure NextPage;
  336.     Procedure PreviousPage;
  337.     Procedure RemoveAllSeries;
  338.     Procedure SeriesDown(ASeries:TChartSeries);
  339.     Procedure SeriesUp(ASeries:TChartSeries);
  340.     procedure UndoZoom; override;
  341.     Procedure ZoomPercent(Const PercentZoom:Double);
  342.     Procedure ZoomRect(Const Rect:TRect);
  343.     Function FormattedValueLegend(ASeries:TChartSeries; ValueIndex:Longint):String; override;
  344.     Function FormattedLegend(SeriesOrValueIndex:Longint):String;
  345.  
  346.     { to be published }
  347.     property BackImageInside:Boolean read FBackImageInside
  348.                      write SetBackImageInside default False;
  349.     property BackColor:TColor read GetBackColor write SetBackColor default clTeeColor;
  350.     property BackWall:TChartWall read FBackWall write SetBackWall;
  351.     property Frame:TChartPen read GetFrame write SetFrame;
  352.     property BottomWall:TChartWall read FBottomWall write SetBottomWall;
  353.     property Foot:TChartTitle read FFoot write SetFoot;
  354.     property LeftWall:TChartWall read FLeftWall write SetLeftWall;
  355.     property Legend:TChartLegend read FLegend write SetLegend;
  356.     property Title:TChartTitle read FTitle write SetTitle;
  357.  
  358.     { events }
  359.     property OnAllowScroll:TChartAllowScrollEvent read FOnAllowScroll write FOnAllowScroll;
  360.     property OnClickAxis:TChartClickAxis read FOnClickAxis write FOnClickAxis;
  361.     property OnClickLegend:TChartClick read FOnClickLegend write FOnClickLegend;
  362.     property OnClickSeries:TChartClickSeries read FOnClickSeries write FOnClickSeries;
  363.     property OnClickBackground:TChartClick read FOnClickbackground write FOnClickBackGround;
  364.     property OnGetLegendPos:TOnGetLegendPos read FOnGetLegendPos write FOnGetLegendPos;
  365.     property OnGetLegendRect:TOnGetLegendRect read FOnGetLegendRect write FOnGetLegendRect;
  366.     property OnGetLegendText:TOnGetLegendText read FOnGetLegendText write FOnGetLegendText;
  367.  
  368.     { TPanel properties }
  369.     property Align;
  370.     property BevelInner;
  371.     property BevelOuter;
  372.     property BevelWidth;
  373.     property BorderWidth;
  374.     property BorderStyle;
  375.     property DragCursor;
  376.     property DragMode;
  377.     property Enabled;
  378.     property ParentColor;
  379.     property ParentShowHint;
  380.     property PopupMenu;
  381.     property ShowHint;
  382.     property TabOrder;
  383.     property TabStop;
  384.     property Visible;
  385.     {$IFDEF D4}
  386.     property AutoSize;
  387.     property Constraints;
  388.     property DragKind;
  389.     {$ENDIF}
  390.  
  391.     { TPanel events }
  392.     property OnClick;
  393.     property OnDblClick;
  394.     property OnDragDrop;
  395.     property OnDragOver;
  396.     property OnEndDrag;
  397.     property OnEnter;
  398.     property OnExit;
  399.     property OnMouseDown;
  400.     property OnMouseMove;
  401.     property OnMouseUp;
  402.     property OnResize;
  403.     {$IFDEF D4}
  404.     property OnCanResize;
  405.     property OnConstrainedResize;
  406.     property OnDockDrop;
  407.     property OnDockOver;
  408.     property OnEndDock;
  409.     property OnGetSiteInfo;
  410.     property OnStartDock;
  411.     property OnUnDock;
  412.     {$ENDIF}
  413.   end;
  414.  
  415.   TChart=class(TCustomChart)
  416.   published
  417.     { TCustomChart Properties }
  418.     property AllowPanning;
  419.     property AllowZoom;
  420.     property AnimatedZoom;
  421.     property AnimatedZoomSteps;
  422.     property BackImage;
  423.     property BackImageInside;
  424.     property BackImageMode;
  425.     property BackWall;
  426.     property BottomWall;
  427.     property Foot;
  428.     property Gradient;
  429.     property LeftWall;
  430.     property MarginBottom;
  431.     property MarginLeft;
  432.     property MarginRight;
  433.     property MarginTop;
  434.     property PrintProportional;
  435.     property Title;
  436.  
  437.     { TCustomChart Events }
  438.     property OnAllowScroll;
  439.     property OnClickAxis;
  440.     property OnClickLegend;
  441.     property OnClickSeries;
  442.     property OnClickBackground;
  443.     property OnGetLegendPos;
  444.     property OnGetLegendRect;
  445.     property OnScroll;
  446.     property OnUndoZoom;
  447.     property OnZoom;
  448.  
  449.     { TCustomAxisPanel properties }
  450.     property AxisVisible;
  451.     property BackColor;
  452.     property BottomAxis;
  453.     property Chart3DPercent;
  454.     property ClipPoints;
  455.     property DepthAxis;
  456.     property Frame;
  457.     property LeftAxis;
  458.     property Legend;
  459.     property MaxPointsPerPage;
  460.     property Monochrome;
  461.     property Page;
  462.     property RightAxis;
  463.     property ScaleLastPage;
  464.     property SeriesList;
  465.     property TopAxis;
  466.     property View3D;
  467.     property View3DOptions;
  468.     property View3DWalls;
  469.  
  470.     { TCustomAxisPanel events }
  471.     property OnAfterDraw;
  472.     property OnBeforeDrawAxes;
  473.     property OnBeforeDrawSeries;
  474.     property OnGetAxisLabel;
  475.     property OnGetLegendText;
  476.     property OnGetNextAxisLabel;
  477.     property OnPageChange;
  478.  
  479.     { TPanel properties }
  480.     property Align;
  481.     property BevelInner;
  482.     property BevelOuter;
  483.     property BevelWidth;
  484.     property BorderWidth;
  485.     property BorderStyle;
  486.     property Color;
  487.     property DragCursor;
  488.     property DragMode;
  489.     property Enabled;
  490.     property ParentColor;
  491.     property ParentShowHint;
  492.     property PopupMenu;
  493.     property ShowHint;
  494.     property TabOrder;
  495.     property TabStop;
  496.     property Visible;
  497.     {$IFDEF D4}
  498.     property AutoSize;
  499.     property Constraints;
  500.     property DragKind;
  501.     {$ENDIF}
  502.  
  503.     { TPanel events }
  504.     property OnClick;
  505.     property OnDblClick;
  506.     property OnDragDrop;
  507.     property OnDragOver;
  508.     property OnEndDrag;
  509.     property OnEnter;
  510.     property OnExit;
  511.     property OnMouseDown;
  512.     property OnMouseMove;
  513.     property OnMouseUp;
  514.     property OnResize;
  515.     {$IFDEF D3}
  516.     property OnStartDrag;
  517.     {$ENDIF}
  518.     {$IFDEF D4}
  519.     property OnCanResize;
  520.     property OnConstrainedResize;
  521.     property OnDockDrop;
  522.     property OnDockOver;
  523.     property OnEndDock;
  524.     property OnStartDock;
  525.     property OnUnDock;
  526.     {$ENDIF}
  527.   end;
  528.  
  529. { This function returns a Brush Style }
  530. Function GetDefaultPattern(PatternIndex:Longint):TBrushStyle;
  531.  
  532. type
  533.   TTeeSeriesType = class
  534.   public
  535.     SeriesClass      : TChartSeriesClass;
  536.     FunctionClass    : TTeeFunctionClass;
  537.     Description      : TeeGalleryString;
  538.     GalleryPage      : TeeGalleryString;
  539.     NumGallerySeries : Integer;
  540.   end;
  541.  
  542.   TTeeSeriesTypes = class(TList)
  543.   private
  544.     Function GetSeriesType(Index:Integer):TTeeSeriesType;
  545.   public
  546.     property SeriesType[Index:Integer]:TTeeSeriesType read GetSeriesType; {$IFNDEF D1}default;{$ENDIF}
  547.   end;
  548.  
  549. Var TeeSeriesTypes : TTeeSeriesTypes;  { List of Series types }
  550.  
  551. {$IFNDEF D1}
  552. type
  553.   TTeeDragObject = class(TDragObject)
  554.   private
  555.     FPart: TChartClickedPart;
  556.   protected
  557. {    function GetDragImages: TCustomImageList; override;}
  558.     function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; override;
  559.     procedure Finished(Target: TObject; X, Y: Integer; Accepted: Boolean); override;
  560.   public
  561.     constructor Create(Const APart: TChartClickedPart);
  562.     property Part: TChartClickedPart read FPart;
  563. {    procedure HideDragImage; override;
  564.     procedure ShowDragImage; override;}
  565.   end;
  566. {$ENDIF}
  567.  
  568. { Adds a new Series component definition for the Gallery }
  569. { Setting ANumGallerySeries to zero makes the Series to not appear on the
  570.   Gallery. }
  571. Procedure RegisterTeeSeries( ASeriesClass:TChartSeriesClass;
  572.                  Const ADescription,AGalleryPage:String;
  573.                  ANumGallerySeries : Integer );
  574.  
  575. { Adds a new Function component definition for the Gallery }
  576. Procedure RegisterTeeFunction( AFunctionClass:TTeeFunctionClass;
  577.                    Const ADescription,AGalleryPage:String;
  578.                    ANumGallerySeries : Integer );
  579.  
  580. { Adds a new Function component to the basic functions gallery }
  581. Procedure RegisterTeeBasicFunction( AFunctionClass:TTeeFunctionClass;
  582.                     Const ADescription:String );
  583.  
  584. { Adds a new Series & Function components definition for the Gallery }
  585. Procedure RegisterTeeSeriesFunction( ASeriesClass:TChartSeriesClass;
  586.                      AFunctionClass:TTeeFunctionClass;
  587.                      Const ADescription,AGalleryPage:String;
  588.                      ANumGallerySeries : Integer );
  589.  
  590. { Removes Series from Gallery }
  591. Procedure UnRegisterTeeSeries(Const ASeriesList:Array of TChartSeriesClass);
  592.  
  593. { Removes Functions from Gallery }
  594. Procedure UnRegisterTeeFunctions(Const AFunctionList:Array of TTeeFunctionClass);
  595.  
  596. { Returns the description string for "FunctionType" TeeFunction class }
  597. Function GetTeeFunctionDescription( AFunctionClass:TTeeFunctionClass):String;
  598.  
  599.  
  600. { Assigns all Series properties from Old to New.
  601.   (Data values are not assigned). }
  602. Procedure AssignSeries(Var OldSeries,NewSeries:TChartSeries);
  603.  
  604. { Creates a new "class" TeeFunction and sets its ParentSeries to ASeries }
  605. Function CreateNewTeeFunction( ASeries:TChartSeries;
  606.                    AClass:TTeeFunctionClass):TTeeFunction;
  607.  
  608. { Creates a new "class" TChartSeries and sets its ParentChart to AChart }
  609. Function CreateNewSeries( AOwner:TComponent;
  610.               AChart:TCustomAxisPanel;
  611.               AClass:TChartSeriesClass;
  612.               AFunctionClass:TTeeFunctionClass):TChartSeries;
  613.  
  614. Function CloneChartSeries(ASeries:TChartSeries):TChartSeries;
  615.  
  616. procedure ChangeSeriesType( Var ASeries:TChartSeries;
  617.                 NewType:TChartSeriesClass );
  618.  
  619. procedure ChangeAllSeriesType( AChart:TCustomChart; AClass:TChartSeriesClass );
  620.  
  621. implementation
  622.  
  623. Uses TeeConst
  624.      {$IFNDEF TEEOCX}
  625.      ,DsgnIntf
  626.      {$ENDIF};
  627.  
  628. Const TeeLegendOff2  = 2;
  629.       TeeLegendOff4  = 4;
  630.  
  631. Function GetDefaultPattern(PatternIndex:Longint):TBrushStyle;
  632.  
  633. Const MaxDefaultPatterns = 6;
  634.       PatternPalette     : Array[1..MaxDefaultPatterns] of TBrushStyle=
  635.     ( bsHorizontal,
  636.       bsVertical,
  637.       bsFDiagonal,
  638.       bsBDiagonal,
  639.       bsCross,
  640.       bsDiagCross
  641.     );
  642. Begin
  643.   result:=PatternPalette[1+(PatternIndex mod MaxDefaultPatterns)];
  644. End;
  645.  
  646. { TChartWall }
  647. Constructor TChartWall.Create(AOwner:TCustomChart);
  648. Begin
  649.   inherited Create;
  650.   FParentChart:=AOwner;
  651.   FColor:=clTeeColor;
  652.   FDark3D:=True;
  653.   DefaultColor:=clTeeColor;
  654.   FBrush:=TChartBrush.Create(ParentChart.CanvasChanged);
  655.   FPen:=TChartPen.Create(ParentChart.CanvasChanged);
  656. End;
  657.  
  658. Destructor TChartWall.Destroy;
  659. Begin
  660.   FPen.Free;
  661.   FBrush.Free;
  662.   inherited Destroy;
  663. End;
  664.  
  665. Function TChartWall.IsColorStored:Boolean;
  666. begin
  667.   result:=FColor<>DefaultColor;
  668. end;
  669.  
  670. Procedure TChartWall.Assign(Source:TPersistent);
  671. Begin
  672.   if Source is TChartWall then
  673.   With TChartWall(Source) do
  674.   Begin
  675.     Self.FBrush.Assign(FBrush);
  676.     Self.FColor   := FColor;
  677.     Self.FDark3D  := FDark3D;
  678.     Self.FPen.Assign(FPen);
  679.     Self.FSize    := FSize;
  680.   end
  681.   else inherited Assign(Source);
  682. End;
  683.  
  684. Function TChartWall.ApplyDark3D:Boolean;
  685. begin
  686.   result:=(FBrush.Style<>bsClear) and (FBrush.Bitmap=nil) and FDark3D;
  687. end;
  688.  
  689. Procedure TChartWall.SetPen(Value:TChartPen);
  690. Begin
  691.   FPen.Assign(Value);
  692. end;
  693.  
  694. Procedure TChartWall.SetBrush(Value:TChartBrush);
  695. Begin
  696.   FBrush.Assign(Value);
  697. End;
  698.  
  699. Procedure TChartWall.SetSize(Value:Longint);
  700. Begin
  701.   ParentChart.SetLongintProperty(FSize,Value);
  702. End;
  703.  
  704. Procedure TChartWall.SetColor(Value:TColor);
  705. Begin
  706.   ParentChart.SetColorProperty(FColor,Value);
  707. End;
  708.  
  709. Procedure TChartWall.SetDark3D(Value:Boolean);
  710. begin
  711.   ParentChart.SetBooleanProperty(FDark3D,Value);
  712. end;
  713.  
  714. { TChartTitle }  { Used in Chart Title and Chart Foot }
  715. Constructor TChartTitle.Create(AOwner: TCustomChart);
  716. Begin
  717.   inherited Create(AOwner);
  718.   FColor:=clTeeColor;
  719.   FText:=TStringList.Create;
  720.   TStringList(FText).OnChange:=ParentChart.CanvasChanged;
  721.   FVisible:=True;
  722.   FAlignment:=taCenter;
  723.   FFont.Color:=clBlue;
  724.   DefaultFontColor:=clBlue;
  725.   DefaultFontStyle:=[];
  726.   FFrame:=TChartHiddenPen.Create(ParentChart.CanvasChanged);
  727.   FAdjustFrame:=True;
  728.   FBrush:=TChartBrush.Create(ParentChart.CanvasChanged);
  729. end;
  730.  
  731. Procedure TChartTitle.Assign(Source:TPersistent);
  732. Begin
  733.   if Source is TChartTitle then
  734.   With TChartTitle(Source) do
  735.   Begin
  736.     Self.FAdjustFrame  := FAdjustFrame;
  737.     Self.FAlignment    := FAlignment;
  738.     Self.FBrush.Assign(FBrush);
  739.     Self.FColor        := FColor;
  740.     Self.FFrame.Assign(FFrame);
  741.     Self.FText.Assign(FText);
  742.     Self.FVisible      := FVisible;
  743.   end;
  744.   inherited Assign(Source);
  745. end;
  746.  
  747. Function TChartTitle.IsFontStored:Boolean;
  748. begin
  749.   With Font do
  750.   result:= (Name<>GetDefaultFontName) or
  751.        (Size<>GetDefaultFontSize) or
  752.        (Color<>DefaultFontColor) or
  753.        (Style<>DefaultFontStyle);
  754. end;
  755.  
  756. Destructor TChartTitle.Destroy;
  757. Begin
  758.   FText.Free;
  759.   FFrame.Free;
  760.   FBrush.Free;
  761.   inherited Destroy;
  762. end;
  763.  
  764. Procedure TChartTitle.SetText(Value:TStrings);
  765. begin
  766.   FText.Assign(Value);
  767.   Repaint;
  768. end;
  769.  
  770. Procedure TChartTitle.SetVisible(Value:Boolean);
  771. begin
  772.   ParentChart.SetBooleanProperty(FVisible,Value);
  773. end;
  774.  
  775. Procedure TChartTitle.SetAdjustFrame(Value:Boolean);
  776. begin
  777.   ParentChart.SetBooleanProperty(FAdjustFrame,Value);
  778. end;
  779.  
  780. Procedure TChartTitle.SetAlignment(Value:TAlignment);
  781. Begin
  782.   if FAlignment<>Value then
  783.   begin
  784.     FAlignment:=Value;
  785.     Repaint;
  786.   end;
  787. end;
  788.  
  789. Procedure TChartTitle.SetBrush(Value:TChartBrush);
  790. begin
  791.   FBrush.Assign(Value);
  792. end;
  793.  
  794. Procedure TChartTitle.SetColor(Value:TColor);
  795. begin
  796.   ParentChart.SetColorProperty(FColor,Value);
  797. end;
  798.  
  799. Procedure TChartTitle.SetFrame(Value:TChartHiddenPen);
  800. begin
  801.   FFrame.Assign(Value);
  802. end;
  803.  
  804. Function TChartTitle.Clicked(x,y:Integer):Boolean;
  805. begin
  806.   result:=FVisible and PtInRect(TitleRect,Classes.Point(x,y));
  807. end;
  808.  
  809. procedure TChartTitle.Draw(OnTop:Boolean);
  810. var R         : TRect;
  811.     tmpMargin : Integer;
  812.  
  813.   Procedure DrawTitleLine(Const St:String);
  814.   Var tmpXPosTitle : Longint;
  815.       tmpWidth     : Longint;
  816.   Begin
  817.     if Alignment=taLeftJustify then tmpXPosTitle:=R.Left+(tmpMargin div 2)
  818.     else
  819.     begin
  820.       tmpWidth:=ParentChart.Canvas.TextWidth(St);
  821.       if Alignment=taRightJustify then
  822.      tmpXPosTitle:=R.Right-tmpWidth-(tmpMargin div 2)
  823.       else { center }
  824.      tmpXPosTitle:=((R.Left+R.Right) div 2)-(tmpWidth div 2);
  825.     end;
  826.     ParentChart.Canvas.TextOut(tmpXPosTitle,R.Top,St);
  827.   end;
  828.  
  829. Var FontH        : Longint;
  830.     t            : Longint;
  831.     tmpWidth     : Longint;
  832.     tmpMaxWidth  : Longint;
  833.     tmp          : Longint;
  834.     tmpFrameVisible : Boolean;
  835.     tmpFrameWidth   : Integer;
  836. Begin
  837.   ParentChart.FontCanvas(Font);
  838.   With ParentChart.Canvas do
  839.   begin
  840.     FontH:=FontHeight;
  841.     if Self.Color=clTeeColor then
  842.     begin
  843.       if Self.Brush.Style=bsSolid then
  844.       begin
  845.     if Self.Brush.Color<>clTeeColor then
  846.     begin
  847.       Self.Color:=Self.Brush.Color;
  848.       Brush.Style:=bsSolid;
  849.     end
  850.     else Brush.Style:=bsClear;
  851.       end
  852.       else
  853.       begin
  854.     Brush.Assign(Self.Brush);
  855.     BackMode:=cbmTransparent;
  856.       end;
  857.     end
  858.     else
  859.     begin
  860.       if Self.Brush.Style=bsSolid then
  861.       begin
  862.     Brush.Style:=bsSolid;
  863.     Brush.Color:=Self.Color;
  864.       end
  865.       else
  866.       begin
  867.     Brush.Assign(Self.Brush);
  868.     BackMode:=cbmOpaque;
  869.     BackColor:=ColorToRGB(Self.Color);
  870.       end;
  871.     end;
  872.   end;
  873.  
  874.   tmpFrameVisible:=Frame.Visible and (Frame.Color<>clTeeColor);
  875.   if tmpFrameVisible then tmpFrameWidth:=Frame.Width
  876.              else tmpFrameWidth:=0;
  877.   R.Left  :=ParentChart.ChartRect.Left+tmpFrameWidth;
  878.   if OnTop then
  879.   Begin
  880.     R.Top:=ParentChart.ChartRect.Top+tmpFrameWidth;
  881.     R.Bottom:=R.Top-5;
  882.   end
  883.   else
  884.   Begin
  885.     R.Bottom:=ParentChart.ChartRect.Bottom-tmpFrameWidth;
  886.     R.Top:=R.Bottom+5;
  887.   end;
  888.   R.Right :=ParentChart.ChartRect.Right-tmpFrameWidth;
  889.   FTitleRect:=R;
  890.   if tmpFrameVisible then
  891.   begin
  892.     ParentChart.Canvas.Pen.Assign(Frame);
  893.     tmpWidth:=Frame.Width;
  894.   end
  895.   else
  896.   begin
  897.     ParentChart.Canvas.Pen.Style:=psClear;
  898.     tmpWidth:=0;
  899.   end;
  900.   if OnTop then FTitleRect.Bottom:=R.Top+Text.Count*FontH
  901.        else FTitleRect.Top   :=R.Bottom-Text.Count*FontH;
  902.   InflateRect(FTitleRect,tmpWidth,tmpWidth);
  903.   tmpMargin:=ParentChart.Canvas.TextWidth('W');
  904.   if tmpFrameVisible or (ParentChart.Canvas.Brush.Style<>bsClear) then
  905.   begin
  906.     if AdjustFrame then
  907.     Begin
  908.       tmpMaxWidth:=0;
  909.       for t:=0 to Text.Count-1 do
  910.       Begin
  911.     tmp:=ParentChart.Canvas.TextWidth(Text[t]);
  912.     if tmp>tmpMaxWidth then tmpMaxWidth:=tmp;
  913.       end;
  914.       tmpMaxWidth:=tmpMaxWidth+tmpMargin;
  915.       With FTitleRect do
  916.       Case Alignment of
  917.     taLeftJustify  : Right:=Left +tmpMaxWidth;
  918.     taRightJustify : Left :=Right-tmpMaxWidth;
  919.     taCenter       : begin
  920.                tmp:=(Left+Right) div 2;
  921.                Left :=tmp-(tmpMaxWidth div 2);
  922.                Right:=tmp+(tmpMaxWidth div 2);
  923.              end;
  924.       end;
  925.     End;
  926.     ParentChart.Canvas.DoRectangle(FTitleRect);
  927.   end;
  928.  
  929.   ParentChart.Canvas.BackMode:=cbmTransparent;
  930.   if OnTop then
  931.   for t:=0 to Text.Count-1 do
  932.   Begin
  933.     R.Bottom:=R.Top+FontH;
  934.     DrawTitleLine(Text[t]);
  935.     R.Top:=R.Bottom;
  936.   end
  937.   else
  938.   for t:=Text.Count-1 downto 0 do
  939.   Begin
  940.     R.Top:=R.Bottom-FontH;
  941.     DrawTitleLine(Text[t]);
  942.     R.Bottom:=R.Top;
  943.   end;
  944.   if tmpFrameVisible then
  945.      if OnTop then Inc(R.Bottom,tmpWidth)
  946.           else Dec(R.Top,tmpWidth);
  947.   With ParentChart.ChartRect do
  948.   if OnTop then Top:=R.Bottom+5
  949.        else Bottom:=R.Top-5;
  950.   ParentChart.RecalcWidthHeight;
  951. end;
  952.  
  953. { TCustomChart }
  954. Constructor TCustomChart.Create(AOwner: TComponent);
  955. Begin
  956.   inherited Create(AOwner);
  957.   FTitle:=TChartTitle.Create(Self);
  958.   FFoot:=TChartTitle.Create(Self);
  959.   if csDesigning in ComponentState then
  960.   Begin
  961.     FTitle.FText.Add(ClassName);
  962.     With FFoot.Font do
  963.     Begin
  964.       Color:=clRed;
  965.       Size:=GetDefaultFontSize;
  966.       Style:=[fsItalic];
  967.     end;
  968.     FFoot.DefaultFontColor:=clRed;
  969.     FFoot.DefaultFontStyle:=[fsItalic];
  970.   end;
  971.   FBackWall :=TChartWall.Create(Self);
  972.   FBackWall.Brush.Style:=bsClear;
  973.  
  974.   FLeftWall :=TChartWall.Create(Self);
  975.   With FLeftWall do
  976.   begin
  977.     Color:=ChartMarkColor;
  978.     DefaultColor:=Color;
  979.   end;
  980.  
  981.   FLegend:=TChartLegend.Create(Self);
  982.  
  983.   FBottomWall:=TChartWall.Create(Self);
  984.   With FBottomWall do
  985.   begin
  986.     Color:=clWhite;
  987.     DefaultColor:=Color;
  988.   end;
  989.  
  990.   CancelMouse:=False;
  991.   FRestoredAxisScales:=True;
  992. end;
  993.  
  994. Destructor TCustomChart.Destroy;
  995. Begin
  996.   FTitle.Free;
  997.   FFoot.Free;
  998.   FBackWall.Free;
  999.   FBackWall:=nil;
  1000.   FBottomWall.Free;
  1001.   FLeftWall.Free;
  1002.   FLegend.Free;
  1003.   inherited Destroy;
  1004. end;
  1005.  
  1006. procedure TCustomChart.SetTitle(Value:TChartTitle);
  1007. begin
  1008.   FTitle.Assign(Value);
  1009. end;
  1010.  
  1011. procedure TCustomChart.SetBackImageInside(Value:Boolean);
  1012. begin
  1013.   SetBooleanProperty(FBackImageInside,Value);
  1014. end;
  1015.  
  1016. procedure TCustomChart.SetFoot(Value:TChartTitle);
  1017. begin
  1018.   FFoot.Assign(Value);
  1019. end;
  1020.  
  1021. Function TCustomChart.FormattedValueLegend(ASeries:TChartSeries; ValueIndex:Longint):String;
  1022. Begin
  1023.   if Assigned(ASeries) then result:=FLegend.FormattedValue(ASeries,ValueIndex)
  1024.                else result:='';
  1025. end;
  1026.  
  1027. Function TCustomChart.FormattedLegend(SeriesOrValueIndex:Longint):String;
  1028. Begin
  1029.   result:=FLegend.FormattedLegend(SeriesOrValueIndex);
  1030.   if Assigned(FOnGetLegendText) then
  1031.      FOnGetLegendText(Self,FLegend.ILegendStyle,SeriesOrValueIndex,result);
  1032. end;
  1033.  
  1034. procedure TCustomChart.SetLegend(Value:TChartLegend);
  1035. begin
  1036.   FLegend.Assign(Value);
  1037. end;
  1038.  
  1039. Function TCustomChart.SaveScales:TAllAxisSavedScales;
  1040.  
  1041. {  "remember" the axis scales when zooming, to restore if unzooming }
  1042.   Procedure SaveAxisScales(Axis:TChartAxis; Var tmp:TAxisSavedScales);
  1043.   begin
  1044.     tmp.Auto:=Axis.Automatic;
  1045.     tmp.AutoMin:=Axis.AutomaticMinimum;
  1046.     tmp.AutoMax:=Axis.AutomaticMaximum;
  1047.     tmp.Min:=Axis.Minimum;
  1048.     tmp.Max:=Axis.Maximum;
  1049.   end;
  1050.  
  1051. begin
  1052.   With Result do
  1053.   begin
  1054.     SaveAxisScales(TopAxis,Top);
  1055.     SaveAxisScales(BottomAxis,Bottom);
  1056.     SaveAxisScales(LeftAxis,Left);
  1057.     SaveAxisScales(RightAxis,Right);
  1058.   end;
  1059. end;
  1060.  
  1061. Procedure TCustomChart.RestoreScales(Const Saved:TAllAxisSavedScales);
  1062.  
  1063. {  restore the "remembered" axis scales when unzooming }
  1064.   Procedure RestoreAxisScales(Axis:TChartAxis; Const tmp:TAxisSavedScales);
  1065.   begin
  1066.     With Axis do
  1067.     begin
  1068.       Automatic:=tmp.Auto;
  1069.       AutomaticMinimum:=tmp.AutoMin;
  1070.       AutomaticMaximum:=tmp.AutoMax;
  1071.       if not Automatic then SetMinMax(tmp.Min,tmp.Max);
  1072.     end;
  1073.   end;
  1074.  
  1075. begin
  1076.   With Saved do
  1077.   begin
  1078.     RestoreAxisScales(TopAxis,Top);
  1079.     RestoreAxisScales(BottomAxis,Bottom);
  1080.     RestoreAxisScales(LeftAxis,Left);
  1081.     RestoreAxisScales(RightAxis,Right);
  1082.   end;
  1083. end;
  1084.  
  1085. procedure TCustomChart.SetBackWall(Value:TChartWall);
  1086. begin
  1087.   FBackWall.Assign(Value);
  1088. end;
  1089.  
  1090. Function TCustomChart.GetFrame:TChartPen;
  1091. begin
  1092.   if Assigned(FBackWall) then result:=FBackWall.Pen
  1093.              else result:=nil;
  1094. end;
  1095.  
  1096. Procedure TCustomChart.SetFrame(Value:TChartPen);
  1097. begin
  1098.   FBackWall.Pen.Assign(Value);
  1099. end;
  1100.  
  1101. Function TCustomChart.GetBackColor:TColor;
  1102. begin
  1103.   result:=FBackWall.Color;
  1104. end;
  1105.  
  1106. Procedure TCustomChart.SetBackColor(Value:TColor);
  1107. begin
  1108.   FBackWall.Color:=Value;
  1109.   { fix 4.01: do not set backwall solid when loading dfms... }
  1110.   if (Parent<>nil) and (not (csLoading in ComponentState)) then
  1111.      FBackWall.Brush.Style:=bsSolid;
  1112. end;
  1113.  
  1114. Function TCustomChart.IsFreeSeriesColor(AColor:TColor; CheckBackground:Boolean):Boolean;
  1115. var t        : Longint;
  1116.     tmpColor : TColor;
  1117. Begin
  1118.   for t:=0 to SeriesCount-1 do
  1119.   Begin
  1120.     tmpColor:=Series[t].SeriesColor;
  1121.     if (tmpColor=AColor) or
  1122.        (CheckBackground and
  1123.        ( (AColor=Color) or (AColor=BackColor) )) then
  1124.     Begin
  1125.       result:=False;
  1126.       exit;
  1127.     end;
  1128.   end;
  1129.   result:=(not CheckBackground) or ( (AColor<>Color) and (AColor<>BackColor) );
  1130. end;
  1131.  
  1132. procedure TCustomChart.SetLeftWall(Value:TChartWall);
  1133. begin
  1134.   FLeftWall.Assign(Value);
  1135. end;
  1136.  
  1137. procedure TCustomChart.SetBottomWall(Value:TChartWall);
  1138. begin
  1139.   FBottomWall.Assign(Value);
  1140. end;
  1141.  
  1142. procedure TCustomChart.DrawTitlesAndLegend;
  1143.  
  1144.   Procedure DrawTitleFoot;
  1145.   Begin
  1146.     if FTitle.Visible then FTitle.Draw(True);
  1147.     if FFoot.Visible then FFoot.Draw(False);
  1148.   end;
  1149.  
  1150. begin
  1151.   { draw title and foot, or draw foot and title, depending
  1152.     if legend is at left/right or at top/bottom. }
  1153.   { top/bottom legends need to leave space for the title and foot
  1154.     before they get displayed.  }
  1155.   Canvas.FrontPlaneBegin;
  1156.   if Legend.Visible And (SeriesList.CountActive>0) then
  1157.   begin
  1158.     if Legend.Vertical then
  1159.     begin
  1160.       Legend.Draw;
  1161.       DrawTitleFoot;
  1162.     end
  1163.     else
  1164.     begin
  1165.       DrawTitleFoot;
  1166.       Legend.Draw;
  1167.     end;
  1168.   end
  1169.   else DrawTitleFoot;
  1170.   Canvas.FrontPlaneEnd;
  1171. end;
  1172.  
  1173. procedure TCustomChart.DrawImage(Const R:TRect);
  1174. begin
  1175.   if (BackImage.Graphic<>nil)
  1176.      and (not FBackImageInside) then DrawBitmap(R,0);
  1177. end;
  1178.  
  1179. Function TCustomChart.CalcWallSize(Axis:TCustomChartAxis):Longint;
  1180. begin
  1181.   result:=0;
  1182.   if View3D and View3DWalls then
  1183.   begin
  1184.     if Axis=LeftAxis then   result:=FLeftWall.FSize   else
  1185.     if Axis=BottomAxis then result:=FBottomWall.FSize
  1186.   end;
  1187. end;
  1188.  
  1189. Procedure TCustomChart.DrawWalls;  { Left and Bottom wall only }
  1190.  
  1191.   Procedure PrepareWallCanvas(AWall:TChartWall);
  1192.   begin
  1193.     With AWall do
  1194.     begin
  1195.       Canvas.AssignVisiblePen(FPen);
  1196.       if FBrush.Bitmap=nil then
  1197.       begin
  1198.     Canvas.Brush.Bitmap:=nil;
  1199.     if (FColor<>clTeeColor) or (FBrush.Style<>bsSolid) then
  1200.        SetBrushCanvas(FColor,FBrush.Style,FBrush.Color)
  1201.     else
  1202.        Canvas.Brush.Style:=bsClear
  1203.       end
  1204.       else Canvas.Brush.Bitmap:=FBrush.Bitmap;
  1205.     end;
  1206.   end;
  1207.  
  1208. var tmpRect:TRect;
  1209. Begin
  1210.   PrepareWallCanvas(FBackWall);
  1211.   With FBackWall do
  1212.   begin
  1213.     if View3D then
  1214.     begin
  1215.       if View3DWalls and (FSize>0) then { <-- trick, was backcolor }
  1216.       With ChartRect do
  1217.     Canvas.Cube( Left-CalcWallSize(LeftAxis),Right,
  1218.              Top,Bottom+CalcWallSize(BottomAxis),Width3D,Width3D+FSize,
  1219.              ApplyDark3D)
  1220.       else
  1221.       With ChartRect do
  1222.        Canvas.RectangleWithZ(Rect(Succ(Left),Pred(Top),Right,Bottom),Width3D);
  1223. {        Canvas.GradientFill( ChartRect,clSilver,clWhite,gdRightLeft);}
  1224.     end
  1225.     else
  1226.     With ChartRect do Canvas.Rectangle(Left,Top,Succ(Right),Bottom);
  1227.  
  1228.     if (BackImage.Graphic<>nil) and FBackImageInside then
  1229.     begin
  1230.       tmpRect:=ChartRect;
  1231.       if Pen.Visible then InflateRect(tmpRect,0,-1);
  1232.       DrawBitmap(tmpRect,Width3D);
  1233.     end;
  1234.   end;
  1235.   if View3D and View3DWalls then
  1236.   begin
  1237.     PrepareWallCanvas(FLeftWall);
  1238.     With FLeftWall,ChartRect do
  1239.     if FSize>0 then
  1240.        Canvas.Cube( Left-FSize,Left,
  1241.             Top,Bottom+CalcWallSize(BottomAxis),0,Width3D+1,
  1242.             ApplyDark3D)
  1243.     else
  1244.        Canvas.RectangleZ(Left,Top,Bottom+CalcWallSize(BottomAxis),0,Width3D+1);
  1245.     PrepareWallCanvas(FBottomWall);
  1246.     With FBottomWall,ChartRect do
  1247.     if FSize>0 then
  1248.        Canvas.Cube(Left,Right,Bottom,Bottom+FSize,0,Width3D,ApplyDark3D)
  1249.     else
  1250.        Canvas.RectangleY(Left,Bottom,Right,0,Width3D);
  1251.   end;
  1252. end;
  1253.  
  1254. Procedure TCustomChart.SeriesUp(ASeries:TChartSeries);
  1255. var t : Longint;
  1256. Begin  { scroll up ASeries in SeriesList. this changes the Z order }
  1257.   t:=SeriesList.IndexOf(ASeries);
  1258.   if t>0 then
  1259.   Begin
  1260.     SeriesList.Exchange(t,t-1);
  1261.     Invalidate;
  1262.   end;
  1263. end;
  1264.  
  1265. Procedure TCustomChart.SeriesDown(ASeries:TChartSeries);
  1266. var t : Longint;
  1267. Begin  { scroll down ASeries in SeriesList. this changes the Z order }
  1268.   t:=SeriesList.IndexOf(ASeries);
  1269.   if t<SeriesCount-1 then
  1270.   Begin
  1271.     SeriesList.Exchange(t,t+1);
  1272.     Invalidate;
  1273.   end;
  1274. end;
  1275.  
  1276. Procedure TCustomChart.NextPage;
  1277. Begin
  1278.   if (MaxPointsPerPage>0) and (Page<NumPages) then Page:=Page+1;
  1279. End;
  1280.  
  1281. Procedure TCustomChart.PreviousPage;
  1282. Begin
  1283.   if (MaxPointsPerPage>0) and (Page>1) then Page:=Page-1;
  1284. End;
  1285.  
  1286. Procedure TCustomChart.RemoveAllSeries;
  1287. Begin
  1288.   While SeriesCount>0 do RemoveSeries(Series[0]);
  1289. End;
  1290.  
  1291. Procedure TCustomChart.DoZoom(Const topi,topf,boti,botf,lefi,leff,rigi,rigf:Double);
  1292.  
  1293.   Procedure ZoomAxis(AAxis:TChartAxis; Const tmpA,tmpB:Double);
  1294.   Begin { apply a portion of the desired zoom to achieve animation }
  1295.     with AAxis do
  1296.       SetMinMax(Minimum+((tmpA-Minimum)/AnimatedZoomFactor),
  1297.         Maximum-((Maximum-tmpB)/AnimatedZoomFactor));
  1298.   end;
  1299.  
  1300. Var t : Longint;
  1301. Begin
  1302.   if FRestoredAxisScales then
  1303.   begin
  1304.     FSavedScales:=SaveScales;
  1305.     FRestoredAxisScales:=False;
  1306.   end;
  1307.   if AnimatedZoom then  {apply animation... }
  1308.     for t:=1 to AnimatedZoomSteps-1 do
  1309.     begin
  1310.       ZoomAxis(LeftAxis,Lefi,Leff);
  1311.       ZoomAxis(RightAxis,Rigi,Rigf);
  1312.       ZoomAxis(TopAxis,Topi,Topf);
  1313.       ZoomAxis(BottomAxis,Boti,Botf);
  1314.       Refresh;
  1315.     end;
  1316.   { final zoom }
  1317.   LeftAxis.SetMinMax(Lefi,Leff);
  1318.   RightAxis.SetMinMax(Rigi,Rigf);
  1319.   TopAxis.SetMinMax(Topi,Topf);
  1320.   BottomAxis.SetMinMax(Boti,Botf);
  1321.   Zoomed:=True;
  1322.   if Assigned(FOnZoom) then FOnZoom(Self);
  1323. end;
  1324.  
  1325. Procedure TCustomChart.ZoomRect(Const Rect:TRect);
  1326. Begin
  1327.   With IZoom do
  1328.   Begin
  1329.     X0:=Rect.Left;
  1330.     Y0:=Rect.Top;
  1331.     X1:=Rect.Right;
  1332.     Y1:=Rect.Bottom;
  1333.     CalcZoomPoints;
  1334.   end;
  1335. End;
  1336.  
  1337. Procedure TCustomChart.ZoomPercent(Const PercentZoom:Double);
  1338.  
  1339.   Procedure CalcAxisScale(Axis:TChartAxis; Var tmpA,tmpB:Double);
  1340.   Var tmpDelta : Double;
  1341.       AMin     : Double;
  1342.       AMax     : Double;
  1343.   Begin
  1344.     AMin:=Axis.Minimum;
  1345.     AMax:=Axis.Maximum;
  1346.     Axis.CalcMinMax(AMin,AMax);
  1347.     tmpDelta:=(AMax-AMin)*(PercentZoom-100.0)*0.01;
  1348.     tmpA:=AMin+tmpDelta;
  1349.     tmpB:=AMax-tmpDelta;
  1350.   end;
  1351.  
  1352. var Lefi : Double;
  1353.     Leff : Double;
  1354.     Rigi : Double;
  1355.     Rigf : Double;
  1356.     Topi : Double;
  1357.     Topf : Double;
  1358.     Boti : Double;
  1359.     Botf : Double;
  1360. Begin  { zoom a given "percent" }
  1361.   CalcAxisScale(LeftAxis,Lefi,Leff);
  1362.   CalcAxisScale(RightAxis,Rigi,Rigf);
  1363.   CalcAxisScale(TopAxis,Topi,Topf);
  1364.   CalcAxisScale(BottomAxis,Boti,Botf);
  1365.   DoZoom(Topi,Topf,Boti,Botf,Lefi,Leff,Rigi,Rigf);
  1366.   Repaint;
  1367. end;
  1368.  
  1369. Procedure TCustomChart.CalcClickedPart( Pos:TPoint; Var Part:TChartClickedPart );
  1370.  
  1371.   Function ClickedAxis(Axis:TCustomChartAxis):Boolean;
  1372.   begin
  1373.     result:=Axis.Clicked(Pos.x,Pos.y);
  1374.     if result then
  1375.     begin
  1376.       Part.Part:=cpAxis;
  1377.       Part.AAxis:=Axis;
  1378.     end;
  1379.   end;
  1380.  
  1381. var t : Longint;
  1382. begin
  1383.   With Part do
  1384.   begin
  1385.     Part:=cpNone;
  1386.     PointIndex:=-1;
  1387.     ASeries:=nil;
  1388.     AAxis:=nil;
  1389.     { IMPORTANT: Z order inverted }
  1390.     for t:=SeriesCount-1 downto 0 do
  1391.     With Self.Series[t] do
  1392.     if Active then
  1393.     Begin
  1394.       PointIndex:=Clicked(Pos.X,Pos.Y);
  1395.       if PointIndex<>-1 then
  1396.       begin
  1397.     ASeries:=Series[t];
  1398.     Part:=cpSeries;
  1399.     Exit;
  1400.       end;
  1401.     end;
  1402.  
  1403.     for t:=0 to FAxes.Count-1 do if ClickedAxis(FAxes[t]) then Exit;
  1404.  
  1405.     if Title.Clicked(Pos.X,Pos.Y) then Part:=cpTitle
  1406.     else
  1407.     if Foot.Clicked(Pos.X,Pos.Y) then  Part:=cpFoot
  1408.     else
  1409.     if PtInRect(ChartRect,Pos) and  { <-- should be PtInCube(ChartRect,0,MaxZ) }
  1410.        (SeriesList.CountActive>0) then
  1411.       Part:=cpChartRect
  1412.     else
  1413.     if Legend.Visible then
  1414.     begin
  1415.       PointIndex:=Legend.Clicked(Pos.X,Pos.Y);
  1416.       if PointIndex<>-1 then Part:=cpLegend;
  1417.     end;
  1418.   end;
  1419. end;
  1420.  
  1421. Function TCustomChart.AxisTitleOrName(Axis:TCustomChartAxis):String;
  1422. Begin
  1423.   result:=Axis.Title.Caption;
  1424.   if result='' then
  1425.   begin
  1426.     if Axis=DepthAxis then result:=TeeMsg_DepthAxis
  1427.     else
  1428.     With Axis do
  1429.     if Horizontal then
  1430.        if OtherSide then result:=TeeMsg_TopAxis
  1431.             else result:=TeeMsg_BottomAxis
  1432.     else
  1433.        if OtherSide then result:=TeeMsg_RightAxis
  1434.             else result:=TeeMsg_LeftAxis;
  1435.   end;
  1436. End;
  1437.  
  1438. procedure TCustomChart.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1439. var IClicked : Boolean;
  1440.  
  1441.     Procedure CheckZoomPanning;
  1442.     Begin
  1443.       if AllowZoom and (Button=TeeZoomMouseButton) and
  1444.      ( TeeZoomKeyShift <= Shift ) then
  1445.       Begin
  1446.     Cursor:=crDefault;
  1447.     IZoom.Activate(x,y);
  1448.     DrawZoomRectangle;
  1449.     IClicked:=True;
  1450.       end;
  1451.       if (AllowPanning<>pmNone) and (Button=TeeScrollMouseButton) and
  1452.      ( TeeScrollKeyShift <= Shift ) then
  1453.       Begin
  1454.     Cursor:=crDefault;
  1455.     IPanning.Activate(x,y);
  1456.     IClicked:=True;
  1457.       end;
  1458.     end;
  1459.  
  1460.     Procedure CheckBackground;
  1461.     begin
  1462.       if Assigned(FOnClickBackground) then
  1463.       begin
  1464.     CancelMouse:=True;
  1465.     FOnClickBackGround(Self,Button,Shift,x,y);
  1466.     IClicked:=CancelMouse;
  1467.       end;
  1468.     end;
  1469.  
  1470. var tmpPart : TChartClickedPart;
  1471. Begin
  1472.   inherited MouseDown(Button,Shift,x,y);
  1473.   if IZoom.Active or IPanning.Active then Exit;
  1474.   if CancelMouse then CancelMouse:=False
  1475.   else
  1476.   begin
  1477.     CalcClickedPart(Classes.Point(x,y),tmpPart);
  1478.     IClicked:=False;
  1479.     Case tmpPart.Part of
  1480.       cpLegend: begin
  1481.           if Assigned(FOnClickLegend) then
  1482.           begin
  1483.             CancelMouse:=True;
  1484.             FOnClickLegend(Self,Button,Shift,x,y);
  1485.             IClicked:=CancelMouse;
  1486.           end;
  1487.         end;
  1488.       cpSeries: Begin
  1489.           With tmpPart do
  1490.           IClicked:=ASeries.DoSeriesClick(ASeries,PointIndex,Button,Shift,x,y);
  1491.           if Assigned(FOnClickSeries) then
  1492.           begin
  1493.             CancelMouse:=True;
  1494.             FOnClickSeries(Self,tmpPart.ASeries,tmpPart.PointIndex,Button,Shift,x,y);
  1495.             IClicked:=CancelMouse;
  1496.           end;
  1497.           if not IClicked then CheckZoomPanning;
  1498.         end;
  1499.     cpAxis: begin
  1500.           if Assigned(FOnClickAxis) then
  1501.           begin
  1502.             CancelMouse:=True;
  1503.             FOnClickAxis(Self,TChartAxis(tmpPart.AAxis),Button,Shift,x,y);
  1504.             IClicked:=CancelMouse;
  1505.           end;
  1506.           if not IClicked then CheckZoomPanning;
  1507.         end;
  1508.    cpChartRect: begin
  1509.           CheckBackground;
  1510.           if not IClicked then CheckZoomPanning;
  1511.         end;
  1512.     end;
  1513.     if not IClicked then CheckBackground;
  1514.     CancelMouse:=False;
  1515.   end;
  1516. End;
  1517.  
  1518. procedure TCustomChart.MouseMove(Shift: TShiftState; X, Y: Integer);
  1519.  
  1520.   Procedure ProcessPanning(Axis:TChartAxis; IniPos,EndPos:Longint);
  1521.   Var Delta          : Double;
  1522.       tmpMin         : Double;
  1523.       tmpMax         : Double;
  1524.       tmpAllowScroll : Boolean;
  1525.   Begin
  1526.     With Axis do
  1527.     begin
  1528.       Delta:=CalcPosPoint(IniPos)-CalcPosPoint(EndPos);
  1529.       tmpMin:=Minimum+Delta;
  1530.       tmpMax:=Maximum+Delta;
  1531.     end;
  1532.     tmpAllowScroll:=True;
  1533.     if Assigned(FOnAllowScroll) then
  1534.        FOnAllowScroll(Axis,tmpMin,tmpMax,tmpAllowScroll);
  1535.     if tmpAllowScroll then Axis.SetMinMax(tmpMin,tmpMax);
  1536.   end;
  1537.  
  1538.   Function CheckMouseSeries:Boolean;
  1539.   Var t : Integer;
  1540.   Begin
  1541.     result:=False;
  1542.     for t:=0 to SeriesCount-1 do
  1543.     With Series[t] do
  1544.     if Active and (Cursor<>crDefault) then
  1545.     begin
  1546.       if Clicked(X,Y)<>-1 then
  1547.       Begin
  1548.     Self.Cursor:=Cursor; { <-- mouse is over a Series point ! }
  1549.     result:=True;
  1550.     break;
  1551.       end;
  1552.     end;
  1553.     for t:=0 to SeriesCount-1 do Series[t].DoSeriesMouseMove(Shift,X,Y);
  1554.    end;
  1555.  
  1556. Var Panned : Boolean;
  1557.  
  1558.    Procedure PanAxis(AxisHorizontal:Boolean; Const Pos1,Pos2:Integer);
  1559.    Var tmpAxis : TChartAxis;
  1560.        t       : Integer;
  1561.        tmpMode : TPanningMode;
  1562.    begin
  1563.      if AxisHorizontal then tmpMode:=pmHorizontal
  1564.                else tmpMode:=pmVertical;
  1565.      if (Pos1<>Pos2) and
  1566.     ( (AllowPanning=tmpMode) or (AllowPanning=pmBoth) ) then
  1567.      Begin
  1568.        for t:=0 to FAxes.Count-1 do
  1569.        begin
  1570.      tmpAxis:=TChartAxis(FAxes[t]);
  1571.      if not tmpAxis.IsDepthAxis then
  1572.         if (AxisHorizontal and tmpAxis.Horizontal) or
  1573.            ((not AxisHorizontal) and (not tmpAxis.Horizontal)) then
  1574.            ProcessPanning(tmpAxis,Pos2,Pos1);
  1575.        end;
  1576.        Panned:=True;
  1577.      end;
  1578.    end;
  1579.  
  1580. Begin
  1581.   inherited MouseMove(Shift,x,y);
  1582.   if csDesigning in ComponentState then Exit;
  1583.   With IZoom do  { zoom }
  1584.   if Active then
  1585.   Begin
  1586.     if (x<>X1) or (y<>Y1) then
  1587.     Begin
  1588.       DrawZoomRectangle;
  1589.       X1:=x;
  1590.       Y1:=y;
  1591.       DrawZoomRectangle;
  1592.     end;
  1593.   end
  1594.   else
  1595.   With IPanning do { scroll }
  1596.   if Active then
  1597.   Begin
  1598.     if PtInRect(ChartRect,Classes.Point(x,y)) then
  1599.     Begin
  1600.       if (x<>X1) or (y<>Y1) then
  1601.       Begin
  1602.     Panned:=False;
  1603.     Check;
  1604.     if FRestoredAxisScales then
  1605.     begin
  1606.       FSavedScales:=SaveScales;
  1607.       FRestoredAxisScales:=False;
  1608.     end;
  1609.  
  1610.     PanAxis(True,X,X1);
  1611.     PanAxis(False,Y,Y1);
  1612.     X1:=x;
  1613.     Y1:=y;
  1614.     if Panned then
  1615.     Begin
  1616.       if Assigned(FOnScroll) then FOnScroll(Self);
  1617.       Invalidate;
  1618.     end;
  1619.       End;
  1620.     end
  1621.     else IPanning.Active:=False;
  1622.   End
  1623.   else
  1624.   if not CheckMouseSeries then Cursor:=OriginalCursor;{ <-- guess cursor shape }
  1625. End;
  1626.  
  1627. procedure TCustomChart.UndoZoom;
  1628. begin
  1629.   if not FRestoredAxisScales then RestoreScales(FSavedScales);
  1630.   FRestoredAxisScales:=True;
  1631.   inherited UndoZoom;
  1632. end;
  1633.  
  1634. Procedure TCustomChart.CalcZoomPoints;
  1635. Begin
  1636.   With IZoom do
  1637.   Begin
  1638.     Check;
  1639.     DoZoom( TopAxis.CalcPosPoint(X0),TopAxis.CalcPosPoint(X1),
  1640.         BottomAxis.CalcPosPoint(X0),BottomAxis.CalcPosPoint(X1),
  1641.         LeftAxis.CalcPosPoint(Y1),LeftAxis.CalcPosPoint(Y0),
  1642.         RightAxis.CalcPosPoint(Y1),RightAxis.CalcPosPoint(Y0));
  1643.   end;
  1644. End;
  1645.  
  1646. procedure TCustomChart.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1647. Const MinZoomDrag=16;
  1648. Var t:Longint;
  1649. Begin
  1650.   inherited MouseUp(Button,Shift,x,y);
  1651.   for t:=0 to SeriesCount-1 do Series[t].DoSeriesMouseUp(Button,Shift,X,Y);
  1652.   if IZoom.Active and (Button=TeeZoomMouseButton) then
  1653.   With IZoom do
  1654.   Begin
  1655.     Active:=False;
  1656.     DrawZoomRectangle;
  1657.     Canvas.Pen.Mode:=pmCopy;
  1658.     X1:=x;
  1659.     Y1:=y;
  1660.     if (Abs(X1-X0)>MinZoomDrag) and (Abs(Y1-Y0)>MinZoomDrag) then
  1661.     Begin
  1662.       if (X1>X0) and (Y1>Y0) then CalcZoomPoints { <-- do zoom in ! }
  1663.                  else UndoZoom;      { <-- do zoom out ! }
  1664.       Invalidate;
  1665.     end;
  1666.   end;
  1667.   IPanning.Active:=False;
  1668. End;
  1669.  
  1670. Procedure TCustomChart.CalcAxisRect;
  1671. var tmpR    : TRect;
  1672.     OldR    : TRect;
  1673.     tmp     : Integer;
  1674.     tmpAxis : TChartAxis;
  1675. Begin
  1676.   with FAxes do
  1677.   for tmp:=0 to FAxes.Count-1 do TChartAxis(FAxes[tmp]).AdjustMaxMin;
  1678.  
  1679.   CalcSize3DWalls;
  1680.   { for orthogonal only }
  1681.   if View3D and View3DOptions.Orthogonal then
  1682.   begin
  1683.     if View3DWalls then tmp:=BackWall.Size
  1684.            else tmp:=0;
  1685.     With ChartRect do
  1686.     begin
  1687.       Dec(Right,Width3D+tmp);
  1688.       Inc(Top,Height3D+tmp);
  1689.     end;
  1690.   end;
  1691.   RecalcWidthHeight;
  1692.  
  1693.   tmpR:=ChartRect;
  1694.   with FAxes do
  1695.   for tmp:=0 to FAxes.Count-1 do
  1696.   begin
  1697.     tmpAxis:=TChartAxis(FAxes[tmp]);
  1698.     if IsAxisVisible(tmpAxis) then
  1699.     Begin
  1700.       OldR:=TmpR;
  1701.       tmpAxis.CalcRect(OldR,tmp<5);  { <-- inflate only for first 4 axes }
  1702.       if IntersectRect(OldR,TmpR,OldR)
  1703.      {$IFDEF D1}
  1704.        <>0
  1705.      {$ENDIF}
  1706.         then tmpR:=OldR;
  1707.     end;
  1708.   end;
  1709.   ChartRect:=tmpR;
  1710.   RecalcWidthHeight;
  1711.   with FAxes do
  1712.   for tmp:=0 to FAxes.Count-1 do TChartAxis(FAxes[tmp]).InternalCalcPositions;
  1713. end;
  1714.  
  1715. Procedure TCustomChart.CalcSeriesRect;
  1716.  
  1717.   Procedure CalcSeriesAxisRect(Axis:TChartAxis);
  1718.   Var tmpR      : TRect;
  1719.       a         : Integer;
  1720.       b         : Integer;
  1721.       tmpSeries : Integer;
  1722.   Begin
  1723.     tmpR:=Rect(0,0,0,0);
  1724.     for tmpSeries:=0 to SeriesCount-1 do
  1725.     With Series[tmpSeries] do
  1726.     if Active then
  1727.        if AssociatedToAxis(Axis) then
  1728.       if Axis.Horizontal then
  1729.       begin
  1730.         CalcHorizMargins(a,b);
  1731.         With tmpR do
  1732.         begin
  1733.           if Axis.AutomaticMinimum then Left :=MaxLong(Left,a);
  1734.           if Axis.AutomaticMaximum then Right:=MaxLong(Right,b);
  1735.         end;
  1736.       end
  1737.       else
  1738.       begin
  1739.         CalcVerticalMargins(a,b);
  1740.         With tmpR do
  1741.         begin
  1742.           if Axis.AutomaticMaximum then Top   :=MaxLong(Top,a);
  1743.           if Axis.AutomaticMinimum then Bottom:=MaxLong(Bottom,b);
  1744.         end;
  1745.       end;
  1746.     Axis.AdjustMaxMinRect(tmpR);
  1747.   end;
  1748.  
  1749. Begin
  1750.   CalcSeriesAxisRect(TopAxis);
  1751.   CalcSeriesAxisRect(LeftAxis);
  1752.   CalcSeriesAxisRect(RightAxis);
  1753.   CalcSeriesAxisRect(BottomAxis);
  1754. end;
  1755.  
  1756. Procedure TCustomChart.Assign(Source:TPersistent);
  1757. begin
  1758.   if Source is TCustomChart then
  1759.   With TCustomChart(Source) do
  1760.   begin
  1761. {    Self.FBackImage.Assign(FBackImage);
  1762.     Self.FBackImageMode   := FBackImageMode; }
  1763.     Self.FBackImageInside := FBackImageInside;
  1764.     Self.FBackWall.Assign(FBackWall);
  1765.     Self.FBottomWall.Assign(FBottomWall);
  1766. {    Self.FGradient.Assign(FGradient);}
  1767.     Self.FLeftWall.Assign(FLeftWall);
  1768.     Self.FLegend.Assign(FLegend);
  1769. {    Self.FAllowPanning    := FAllowPanning;
  1770.     Self.FAllowZoom       := FAllowZoom;
  1771.     Self.FAnimatedZoom    := FAnimatedZoom;
  1772.     Self.FAnimatedZoomSteps:=FAnimatedZoomSteps;}
  1773.     Self.FFoot.Assign(FFoot);
  1774.     Self.FTitle.Assign(FTitle);
  1775.   end;
  1776.   inherited Assign(Source);
  1777. end;
  1778.  
  1779. Procedure TCustomChart.ExchangeSeries(Series1,Series2:Longint);
  1780. var tmp : Integer;
  1781. begin
  1782.   SeriesList.Exchange(Series1,Series2);
  1783.   tmp:=Series[Series1].ComponentIndex;
  1784.   Series[Series1].ComponentIndex:=Series[Series2].ComponentIndex;
  1785.   Series[Series2].ComponentIndex:=tmp;
  1786.   Repaint;
  1787. end;
  1788. (*
  1789. function TCustomChart.GetPalette: HPALETTE;
  1790. begin
  1791.   Result := 0;  { default result is no palette }
  1792.   if Assigned(FBackImage) and (FBackImage.Graphic<>nil) and
  1793.      (FBackImage.Graphic is TBitmap) then       { only bitmaps have palettes }
  1794.      Result := TBitmap(FBackImage.Graphic).Palette; { use it if available }
  1795. end;
  1796. *)
  1797. Procedure TCustomChart.FillSeriesSourceItems( ASeries:TChartSeries;
  1798.                     Proc:TGetStrProc);
  1799. begin { abstract }
  1800. end;
  1801.  
  1802. Procedure TCustomChart.FillValueSourceItems( ValueList:TChartValueList;
  1803.                        Proc:TGetStrProc);
  1804. Var t:Integer;
  1805. Begin
  1806.   With ValueList.Owner do
  1807.   if (DataSource<>nil) and (DataSource is TChartSeries) then
  1808.      With TChartSeries(DataSource) do
  1809.      for t:=0 to ValuesLists.Count-1 do Proc(ValuesLists.ValueList[t].Name);
  1810. end;
  1811.  
  1812. Function TCustomChart.GetASeries:TChartSeries;
  1813. var t : Integer;
  1814. Begin
  1815.   for t:=0 to SeriesCount-1 do
  1816.   if Series[t].Active then
  1817.   begin
  1818.     result:=SeriesList[t];
  1819.     exit;
  1820.   end;
  1821.   result:=nil;
  1822. End;
  1823.  
  1824. { TChartLegend Sub-Component }
  1825. Constructor TCustomChartLegend.Create(AOwner:TCustomChart);
  1826. begin
  1827.   inherited Create(AOwner);
  1828.   FVisible:=True;
  1829.   FAlignment:=laRight;
  1830.   ILegendStyle:=lsAuto;
  1831.   FMaxNumRows:=10;
  1832.   FColor:=clWhite;
  1833.   FFrame:=TChartPen.Create(ParentChart.CanvasChanged);
  1834.   FTextStyle:=ltsLeftValue;
  1835.   FLegendStyle:=lsAuto;
  1836.   FColorWidth:=12;
  1837.   FTopLeftPos:=10; { 10 % }
  1838.   FResizeChart:=True;
  1839.   FShadowColor:=clBlack;
  1840.   FShadowSize:=3;
  1841.   FDividingLines:=TChartHiddenPen.Create(ParentChart.CanvasChanged);
  1842.   FBrush:=TChartBrush.Create(ParentChart.CanvasChanged);
  1843. end;
  1844.  
  1845. Destructor TCustomChartLegend.Destroy;
  1846. begin
  1847.   FDividingLines.Free;
  1848.   FFrame.Free;
  1849.   FBrush.Free;
  1850.   Inherited Destroy;
  1851. end;
  1852.  
  1853. Procedure TCustomChartLegend.Assign(Source:TPersistent);
  1854. Begin
  1855.   if Source is TCustomChartLegend then
  1856.   With TCustomChartLegend(Source) do
  1857.   Begin
  1858.     Self.FVisible    :=FVisible;
  1859.     Self.FLegendStyle:=FLegendStyle;
  1860.     Self.FFirstValue :=FFirstValue;
  1861.     Self.FAlignment  :=FAlignment;
  1862.     Self.FTextStyle  :=FTextStyle;
  1863.     Self.FColorWidth :=FColorWidth;
  1864.     Self.FHorizMargin:=FHorizMargin;
  1865.     Self.FVertMargin :=FVertMargin;
  1866.     Self.FResizeChart:=FResizeChart;
  1867.     Self.FInverted   :=FInverted;
  1868.     Self.FTopLeftPos :=FTopLeftPos;
  1869.     Self.FColor      :=FColor;
  1870.     Self.FFrame.Assign(FFrame);
  1871.     Self.FMaxNumRows :=FMaxNumRows;
  1872.     Self.FBrush.Assign(FBrush);
  1873.   end;
  1874.   inherited Assign(Source);
  1875. end;
  1876.  
  1877. Procedure TCustomChartLegend.SetVisible(Value:Boolean);
  1878. Begin
  1879.   ParentChart.SetBooleanProperty(FVisible,Value);
  1880. end;
  1881.  
  1882. Procedure TCustomChartLegend.SetInverted(Value:Boolean);
  1883. Begin
  1884.   ParentChart.SetBooleanProperty(FInverted,Value);
  1885. end;
  1886.  
  1887. Procedure TCustomChartLegend.SetAlignment(Value:TLegendAlignment);
  1888. Begin
  1889.   if FAlignment<>Value then
  1890.   begin
  1891.     FAlignment:=Value;
  1892.     Repaint;
  1893.   end;
  1894. end;
  1895.  
  1896. Procedure TCustomChartLegend.SetFrame(Value:TChartPen);
  1897. Begin
  1898.   FFrame.Assign(Value);
  1899. end;
  1900.  
  1901. procedure TCustomChartLegend.CMVisibleChanged(var Message: TMessage);
  1902. Begin
  1903.   Repaint;
  1904. end;
  1905.  
  1906. procedure TCustomChartLegend.CMColorChanged(var Message: TMessage);
  1907. Begin
  1908.   Repaint;
  1909. end;
  1910.  
  1911. Procedure TCustomChartLegend.SetTopLeftPos(Value:Integer);
  1912. Begin
  1913.   if (Value<0) or (Value>100) then
  1914.      Raise LegendException.Create(TeeMsg_LegendTopPos)
  1915.   else
  1916.     ParentChart.SetIntegerProperty(FTopLeftPos,Value);
  1917. end;
  1918.  
  1919. Procedure TCustomChartLegend.SetFirstValue(Value:Longint);
  1920. Begin
  1921.   if Value<0 then
  1922.      Raise LegendException.Create(TeeMsg_LegendFirstValue)
  1923.   else
  1924.      ParentChart.SetLongintProperty(FFirstValue,Value);
  1925. End;
  1926.  
  1927. Procedure TCustomChartLegend.SetTextStyle(Value:TLegendTextStyle);
  1928. Begin
  1929.   if FTextStyle<>Value then
  1930.   begin
  1931.     FTextStyle:=Value;
  1932.     Repaint;
  1933.   end;
  1934. end;
  1935.  
  1936. Procedure TCustomChartLegend.SetMaxNumRows(Value:Integer);
  1937. Begin
  1938.   ParentChart.SetIntegerProperty(FMaxNumRows,Value);
  1939. end;
  1940.  
  1941. Procedure TCustomChartLegend.SetLegendStyle(Value:TLegendStyle);
  1942. Begin
  1943.   if FLegendStyle<>Value then
  1944.   begin
  1945.     FLegendStyle:=Value;
  1946.     CalcLegendStyle; { <-- force recalc of ILegendStyle }
  1947.     Repaint;
  1948.   end;
  1949. end;
  1950.  
  1951. Procedure TCustomChartLegend.SetHorizMargin(Value:Integer);
  1952. Begin
  1953.   ParentChart.SetIntegerProperty(FHorizMargin,Value);
  1954. end;
  1955.  
  1956. Procedure TCustomChartLegend.SetVertMargin(Value:Integer);
  1957. Begin
  1958.   ParentChart.SetIntegerProperty(FVertMargin,Value);
  1959. end;
  1960.  
  1961. Function TCustomChartLegend.GetParentChart:TCustomChart;
  1962. begin
  1963.   result:=TCustomChart(inherited ParentChart);
  1964. end;
  1965.  
  1966. Procedure TCustomChartLegend.SetResizeChart(Value:Boolean);
  1967. Begin
  1968.   ParentChart.SetBooleanProperty(FResizeChart,Value);
  1969. end;
  1970.  
  1971. Procedure TCustomChartLegend.SetBrush(Value:TChartBrush);
  1972. begin
  1973.   FBrush.Assign(Value);
  1974. end;
  1975.  
  1976. Procedure TCustomChartLegend.SetColor(Value:TColor);
  1977. Begin
  1978.   ParentChart.SetColorProperty(FColor,Value);
  1979. end;
  1980.  
  1981. Procedure TCustomChartLegend.SetColorWidth(Value:Integer);
  1982. Begin
  1983.   if (Value<0) or (Value>100) then
  1984.      Raise LegendException.Create(TeeMsg_LegendColorWidth)
  1985.   else
  1986.      ParentChart.SetIntegerProperty(FColorWidth,Value);
  1987. end;
  1988.  
  1989. Procedure TCustomChartLegend.CalcLegendStyle;
  1990. begin
  1991.   if FLegendStyle=lsAuto then
  1992.   begin
  1993.     if ParentChart.SeriesList.CountActive>1 then
  1994.        ILegendStyle:=lsSeries
  1995.     else
  1996.        ILegendStyle:=lsValues;
  1997.   end
  1998.   else ILegendStyle:=FLegendStyle;
  1999. end;
  2000.  
  2001. Function TCustomChartLegend.FormattedLegend(SeriesOrValueIndex:Longint):String;
  2002. Begin
  2003.   With ParentChart do
  2004.   Case ILegendStyle of
  2005.     lsSeries:     result:=SeriesTitleLegend(SeriesOrValueIndex);
  2006.     lsValues:     result:=FormattedValueLegend( GetASeries,SeriesOrValueIndex );
  2007.     lsLastValues: result:=FormattedValueLegend( Series[SeriesOrValueIndex],
  2008.                         Series[SeriesOrValueIndex].Count-1);
  2009.   end;
  2010. end;
  2011.  
  2012. Procedure TCustomChartLegend.SetShadowColor(Value:TColor);
  2013. begin
  2014.   ParentChart.SetColorProperty(FShadowColor,Value);
  2015. end;
  2016.  
  2017. Procedure TCustomChartLegend.SetShadowSize(Value:Integer);
  2018. begin
  2019.   ParentChart.SetIntegerProperty(FShadowSize,Value);
  2020. end;
  2021.  
  2022. Procedure TCustomChartLegend.SetDividingLines(Value:TChartHiddenPen);
  2023. begin
  2024.   FDividingLines.Assign(Value);
  2025. end;
  2026.  
  2027. Function TCustomChartLegend.MaxLegendValues(YLegend,ItemHeight:Longint):Longint;
  2028.  
  2029.   Function CalcMaxLegendValues(A,B,C:Longint):Longint;
  2030.   begin
  2031.     With ParentChart do
  2032.     Begin
  2033.       if (YLegend<A) and (ItemHeight>0) then
  2034.       Begin
  2035.     result:=((B-2*Self.Frame.Width)-YLegend+C) div ItemHeight;
  2036.     result:=MinLong(result,TotalLegendItems);
  2037.       end
  2038.       else result:=0;
  2039.     end;
  2040.   end;
  2041.  
  2042. Begin
  2043.   With ParentChart do
  2044.   if Self.Vertical then
  2045.      result:=CalcMaxLegendValues(ChartRect.Bottom,ChartHeight,ChartRect.Top)
  2046.   else
  2047.      result:=CalcMaxLegendValues(ChartRect.Right,ChartWidth,0);
  2048. end;
  2049.  
  2050. Function TCustomChartLegend.TotalLegendItems:Longint;
  2051. var tmpSeries : TChartSeries;
  2052.     t         : Longint;
  2053. begin
  2054.   result:=0;
  2055.   if (InternalLegendStyle=lsSeries) or (InternalLegendStyle=lsLastValues) then
  2056.   begin
  2057.     for t:=0 to ParentChart.SeriesCount-1 do
  2058.     begin
  2059.       With ParentChart.Series[t] do
  2060.       if Active and ShowInLegend then Inc(result);
  2061.     end;
  2062.     Dec(result,FirstValue);
  2063.   end
  2064.   else
  2065.   begin
  2066.     tmpSeries:=ParentChart.GetASeries;
  2067.     if Assigned(tmpSeries) and (tmpSeries.ShowInLegend) then
  2068.        result:=tmpSeries.CountLegendItems-FirstValue;
  2069.   end;
  2070.   result:=MaxLong(0,result);
  2071. end;
  2072.  
  2073. Function TCustomChartLegend.MaxLegendWidth(NumLegendValues:Longint):Longint;
  2074. var t               : Longint;
  2075.     LastLegendIndex : Longint;
  2076. Begin
  2077.   result:=0;
  2078.   if NumLegendValues=TeeAllValues then
  2079.      LastLegendIndex:=TotalLegendItems+FirstValue-1
  2080.   else
  2081.      LastLegendIndex:=FirstValue+NumLegendValues-1;
  2082.   With ParentChart do
  2083.   for t:=FirstValue to LastLegendIndex do
  2084.       result:=MaxLong(result,Canvas.TextWidth(FormattedLegend(t)));
  2085. end;
  2086.  
  2087. Function TCustomChartLegend.GetColorRect(X1,Y0,Y1:Longint):TRect;
  2088. begin
  2089.   With result do
  2090.   begin
  2091.     Left   :=X1-IColorWidth;
  2092.     Right  :=Left+IColorWidth;
  2093.     Top    :=Y0+2;
  2094.     Bottom :=Y1-2;
  2095.   end;
  2096. end;
  2097.  
  2098. Function TCustomChartLegend.GetVertical:Boolean;
  2099. begin
  2100.   result:=(Alignment=laLeft) or (Alignment=laRight)
  2101. end;
  2102.  
  2103. Procedure TCustomChartLegend.Draw;
  2104. Var XLegendText  : Longint;
  2105.     XLegendColor : Longint;
  2106.     tmpMaxWidth  : Longint;
  2107.     ItemHeight   : Longint;
  2108.     tmpSeries    : TChartSeries;
  2109.     tmpTotalItems: Longint;
  2110.  
  2111.   Procedure DrawLegendItem(ItemIndex,ItemOrder:Longint);
  2112.   Var PosXLegend : Longint;
  2113.       PosYLegend : Longint;
  2114.       R          : TRect;
  2115.       tmpSt      : String;
  2116.   Begin
  2117.     if ItemOrder>=tmpTotalItems then exit;
  2118.     with ParentChart,Canvas do
  2119.     begin
  2120.       Brush.Style:=bsSolid;
  2121.       Brush.Color:=Self.Color;
  2122.  
  2123.       posXLegend:=XLegendText;
  2124.       posYLegend:=RectLegend.Top+1;
  2125.       if Self.Vertical then Inc(posYLegend,ItemOrder*ItemHeight)
  2126.       else
  2127.       begin
  2128.     Inc(posYLegend,(ItemOrder div NumCols)*ItemHeight);
  2129.     Inc(posXLegend,(tmpMaxWidth+IColorWidth+TeeLegendOff4)*(ItemOrder mod NumCols));
  2130.       end;
  2131.  
  2132.       if Assigned(FOnGetLegendPos) then
  2133.      FOnGetLegendPos(ParentChart,ItemIndex,posXLegend,posYLegend,XLegendColor);
  2134.  
  2135.       Brush.Style:=bsClear;
  2136.       tmpSt:=FormattedLegend(ItemIndex);
  2137.  
  2138.       if tmpSt<>'' then
  2139.       begin
  2140.     TextOut(posXLegend,posYLegend,tmpSt);
  2141.     R:=GetColorRect(posXLegend-TeeLegendOff4,posYLegend,posYLegend+ItemHeight);
  2142.  
  2143.     if (InternalLegendStyle=lsSeries) or (InternalLegendStyle=lsLastValues) then
  2144.        ActiveSeriesLegend(ItemIndex).DrawLegend(-1,R)
  2145.     else
  2146.     Begin
  2147.       if Assigned(tmpSeries) then
  2148.          tmpSeries.DrawLegend(tmpSeries.LegendToValueIndex(ItemIndex),R)
  2149.       else
  2150.       Begin
  2151.         Brush.Color:=clWhite;
  2152.         Brush.Style:=bsSolid;
  2153.         DoRectangle(R);
  2154.       end;
  2155.     end;
  2156.       end;
  2157.       if (ItemOrder>0) and (FDividingLines.Visible) then
  2158.       begin
  2159.     Canvas.Pen.Assign(FDividingLines);
  2160.     Canvas.BackMode:=cbmTransparent;
  2161.     if Self.Vertical then
  2162.        DoHorizLine( RectLegend.Left,RectLegend.Right,PosYLegend )
  2163.     else
  2164.        DoVertLine( R.Left-TeeLegendOff4,RectLegend.Top,RectLegend.Bottom );
  2165.       end;
  2166.     end;
  2167.   end;
  2168.  
  2169. Var FrameWidth : Integer;
  2170.  
  2171.   Procedure DrawLegendBackground;
  2172.   var tmpRect      : TRect;
  2173.       tmpPosShadow : Integer;
  2174.   begin
  2175.     tmpRect:=RectLegend;
  2176.     With ParentChart.Canvas do
  2177.     begin
  2178.       AssignVisiblePen(Self.Frame);
  2179.       if Self.Frame.Visible then
  2180.       Begin
  2181.     if Pen.Color=clTeeColor then Pen.Color:=clBlack;
  2182.     InflateRect(tmpRect,FrameWidth,FrameWidth);
  2183.     tmpPosShadow:=FShadowSize+FrameWidth+( (FrameWidth-1) div 2);
  2184.       end
  2185.       else tmpPosShadow:=FShadowSize-1;
  2186.       Brush.Style:=bsSolid;
  2187.       if FShadowSize>0 then
  2188.       begin
  2189.     Brush.Color:=FShadowColor;
  2190.     with RectLegend do
  2191.          FillRect(Rect( Left+FShadowSize,Top+FShadowSize,
  2192.                 Right+tmpPosShadow,Bottom+tmpPosShadow ));
  2193.       end;
  2194.       Brush.Assign(Self.FBrush);
  2195.       if Brush.Style=bsSolid then Brush.Color:=Self.Color
  2196.                  else
  2197.                  begin
  2198.                    BackColor:=Self.Color;
  2199.                    BackMode:=cbmOpaque;
  2200.                  end;
  2201.       if Self.FBrush.Bitmap<>nil then Brush.Bitmap:=Self.FBrush.Bitmap;
  2202. {      GradientFill(tmpRect,clSilver,clWhite,gdRightLeft);}
  2203.       DoRectangle(tmpRect);
  2204.     end;
  2205.   end;
  2206.  
  2207. var t              : Longint;
  2208.     NumLegendItems : Longint;
  2209.     HalfMaxWidth   : Longint;
  2210.     tmpLastValue   : Longint;
  2211.  
  2212.   Procedure CalcHorizontalColsRows;
  2213.   begin
  2214.     NumCols:=MaxLegendValues(2*TeeLegendOff4,tmpMaxWidth+IColorWidth+2*TeeLegendOff4);
  2215.     if NumCols>0 then
  2216.     begin
  2217.       NumRows:=tmpTotalItems div NumCols;
  2218.       if (tmpTotalItems mod NumCols)>0 then Inc(NumRows);
  2219.       NumRows:=MinLong(NumRows,MaxNumRows);
  2220.     end
  2221.     else NumRows:=0;
  2222.   end;
  2223.  
  2224.   Function CalcHorizMargin:Integer;
  2225.   begin
  2226.     if HorizMargin=0 then result:=MulDiv(TeeDefHorizMargin,ParentChart.ChartWidth,100)
  2227.              else result:=HorizMargin;
  2228.   end;
  2229.  
  2230.   Function CalcVertMargin:Integer;
  2231.   begin
  2232.     if VertMargin=0 then result:=MulDiv(TeeDefVerticalMargin,ParentChart.ChartHeight,100)
  2233.             else result:=VertMargin;
  2234.   end;
  2235.  
  2236. Var tmpRect : TRect;
  2237.     tmpW    : Integer;
  2238. Begin
  2239.   CalcLegendStyle;
  2240.   With ParentChart do
  2241.   Begin
  2242.     LegendColor:=FColor;
  2243.     FontCanvas(Self.Font);
  2244.     ItemHeight:=Canvas.FontHeight;
  2245.  
  2246.     tmpMaxWidth:=MaxLegendWidth(TeeAllValues)+TeeLegendOff4;
  2247.     IColorWidth:=Round(ColorWidth*tmpMaxWidth*0.01);
  2248.  
  2249.     tmpTotalItems:=TotalLegendItems;
  2250.     FrameWidth:=Self.Frame.Width;
  2251.  
  2252.     With FRectLegend do
  2253.     Case Self.Alignment of
  2254.     laBottom: begin
  2255.         Bottom:=ChartRect.Bottom-FShadowSize;
  2256.         if Self.Frame.Visible then Dec(Bottom,FrameWidth+1);
  2257.         CalcHorizontalColsRows;
  2258.         Top:=Bottom-TeeLegendOff2-ItemHeight*NumRows;
  2259.           end;
  2260.     laTop:    begin
  2261.         Top:=ChartRect.Top;
  2262.         if Self.Frame.Visible then Inc(Top,FrameWidth+1);
  2263.         CalcHorizontalColsRows;
  2264.         Bottom:=Top+TeeLegendOff2+ItemHeight*NumRows;
  2265.           end;
  2266.     else
  2267.       begin
  2268.     Top:=ChartBounds.Top+Round(1.0*FTopLeftPos*(ChartBounds.Bottom-ChartBounds.Top)*0.01);
  2269.     NumCols:=1;
  2270.     NumRows:=MaxLegendValues(Top,ItemHeight);
  2271.     Bottom:=Top+TeeLegendOff2+ItemHeight*NumRows;
  2272.       end;
  2273.     end;
  2274.  
  2275.     NumLegendItems:=0;
  2276.  
  2277.     With FRectLegend do
  2278.     Case Self.Alignment of
  2279.     laLeft:
  2280.     Begin
  2281.       tmpMaxWidth     :=MaxLegendWidth(NumRows);
  2282.       Left            :=ChartRect.Left;
  2283.       if Self.Frame.Visible then Inc(Left,FrameWidth+1);
  2284.       XLegendColor    :=Left+TeeLegendOff4;
  2285.       IColorWidth     :=Round(ColorWidth*((XLegendColor+TeeLegendOff4+tmpMaxWidth+TeeLegendOff2)-Left)*0.01);
  2286.       XLegendText     :=XLegendColor+IColorWidth+TeeLegendOff4;
  2287.       Right           :=XLegendText+tmpMaxWidth+TeeLegendOff2;
  2288.       NumLegendItems  :=NumRows;
  2289.     end;
  2290.     laRight:
  2291.     begin
  2292.       tmpMaxWidth     :=MaxLegendWidth(NumRows);
  2293.       Right           :=ChartRect.Right;
  2294.       if Self.Frame.Visible then Dec(Right,FrameWidth+1);
  2295.       Dec(Right,FShadowSize);
  2296.       XLegendText     :=Right-tmpMaxWidth-TeeLegendOff2;
  2297.       IColorWidth     :=Round(ColorWidth*(Right-(XLegendText-TeeLegendOff4-TeeLegendOff4))*0.01);
  2298.       XLegendColor    :=XLegendText-IColorWidth-TeeLegendOff4;
  2299.       Left            :=XLegendColor-TeeLegendOff4;
  2300.       NumLegendItems  :=NumRows;
  2301.     end;
  2302.     laTop,
  2303.     laBottom:
  2304.     begin
  2305.       HalfMaxWidth    :=2*TeeLegendOff4+ ((tmpMaxWidth+IColorWidth+TeeLegendOff4)*NumCols);
  2306.       HalfMaxWidth    :=MinLong(ChartWidth,HalfMaxWidth+2*FShadowSize);
  2307.       tmpW:=Round(1.0*FTopLeftPos*(ChartBounds.Right-ChartBounds.Left-HalfMaxWidth)*0.01);
  2308.       HalfMaxWidth    :=HalfMaxWidth div 2;
  2309.       Left            :=ChartXCenter-HalfMaxWidth+tmpW;
  2310.       Right           :=ChartXCenter+HalfMaxWidth+tmpW;
  2311.       XLegendColor    :=Left+TeeLegendOff4;
  2312.       XLegendText     :=XLegendColor+IColorWidth+TeeLegendOff4;
  2313.       NumLegendItems  :=NumCols*NumRows;
  2314.     end;
  2315.     end;
  2316.  
  2317.     if Assigned(FOnGetLegendRect) then
  2318.     begin
  2319.       tmpRect:=RectLegend;
  2320.       FOnGetLegendRect(ParentChart,tmpRect);
  2321.       RectLegend:=tmpRect;
  2322.     end;
  2323.  
  2324.     if NumLegendItems>0 then
  2325.     begin
  2326.       DrawLegendBackground;
  2327.  
  2328.       With Canvas.Pen do
  2329.       begin
  2330.     if Self.Color=clBlack then Color:=clWhite
  2331.                   else Color:=clBlack;
  2332.     Style:=psSolid;
  2333.     Width:=1;
  2334.       end;
  2335.       tmpSeries:=GetASeries;
  2336.       tmpLastValue:=FirstValue+MinLong(tmpTotalItems,NumLegendItems)-1;
  2337.       if Inverted then
  2338.      for t:=tmpLastValue downto FirstValue do DrawLegendItem(t,(tmpLastValue-t))
  2339.       else
  2340.      for t:=FirstValue to tmpLastValue do DrawLegendItem(t,(t-FirstValue));
  2341.  
  2342.       With ChartRect do
  2343.       begin
  2344.     if ResizeChart then
  2345.     Case Self.Alignment of
  2346.       laLeft   : Left  :=RectLegend.Right;
  2347.       laRight  : Right :=RectLegend.Left;
  2348.       laTop    : Top   :=RectLegend.Bottom+FShadowSize;
  2349.       laBottom : Bottom:=RectLegend.Top;
  2350.     end;
  2351.     Case Self.Alignment of
  2352.       laLeft   : Inc(Left,CalcHorizMargin);
  2353.       laRight  : Dec(Right,CalcHorizMargin);
  2354.       laTop    : Inc(Top,CalcVertMargin);
  2355.       laBottom : Dec(Bottom,CalcVertMargin);
  2356.     end;
  2357.       end;
  2358.       ReCalcWidthHeight;
  2359.     end;
  2360.   end;
  2361. end;
  2362.  
  2363. Function TCustomChartLegend.FormattedValue(ASeries:TChartSeries; ValueIndex:Longint):String;
  2364. Var i : Integer;
  2365. begin
  2366.   if ValueIndex<>TeeAllValues then
  2367.   begin
  2368.     result:=ASeries.LegendString(ValueIndex,TextStyle);
  2369.     { eliminate breaks in string... }
  2370.     Repeat
  2371.       i:=AnsiPos(TeeLineSeparator,Result);
  2372.       if i>0 then Result[i]:=' ';
  2373.     Until i=0;
  2374.   end
  2375.   else result:='';
  2376. end;
  2377.  
  2378. Function TCustomChartLegend.Clicked(x,y:Integer):Integer;
  2379.  
  2380. Var tmpH : Integer;
  2381.  
  2382.   Function ClickedRow:Integer;
  2383.   var t    : Integer;
  2384.       tmp  : Integer;
  2385.   begin
  2386.     result:=-1;
  2387.     for t:=0 to NumRows-1 do
  2388.     begin
  2389.       tmp:=RectLegend.Top+1+t*tmpH;
  2390.       if (y>=tmp) and (y<=(tmp+tmpH)) then
  2391.       begin
  2392.     result:=t;
  2393.     Break;
  2394.       end;
  2395.     end;
  2396.   end;
  2397.  
  2398. var t    : Integer;
  2399.     tmp2 : Integer;
  2400.     tmpW : Integer;
  2401. begin
  2402.   result:=-1;
  2403.   if PtInRect(RectLegend,Classes.Point(x,y)) then { inside legend }
  2404.   begin
  2405.     if Vertical then
  2406.     begin
  2407.       if NumRows>0 then
  2408.       begin
  2409.     tmpH:=(RectLegend.Bottom-RectLegend.Top) div NumRows;
  2410.     result:=ClickedRow;
  2411.       end;
  2412.     end
  2413.     else
  2414.     begin
  2415.       if NumCols>0 then
  2416.       begin
  2417.     tmpW:=(RectLegend.Right-RectLegend.Left) div NumCols;
  2418.     tmpH:=ParentChart.Canvas.FontHeight;
  2419.     for t:=0 to NumCols-1 do
  2420.     begin
  2421.       tmp2:=RectLegend.Left+1+t*tmpW;
  2422.       if (x>=tmp2) and (x<=(tmp2+tmpW)) then
  2423.       begin
  2424.         result:=ClickedRow;
  2425.         if result<>-1 then result:=t+NumCols*result;
  2426.       end;
  2427.     end;
  2428.       end;
  2429.     end;
  2430.   end;
  2431. end;
  2432.  
  2433. Function GetNewSeriesName(AOwner:TComponent):String;
  2434. begin
  2435.   result:=TeeGetUniqueName(AOwner,TeeMsg_DefaultSeriesName);
  2436. end;
  2437.  
  2438. Function GetNewFunctionName(AOwner:TComponent):String;
  2439. Var tmp   : Longint;
  2440.     tmpSt : String;
  2441. begin
  2442.   tmp:=1;
  2443.   tmpSt:=TeeMsg_DefaultFunctionName+IntToStr(tmp);
  2444.   while (AOwner.FindComponent(tmpSt)<>nil) do
  2445.   begin
  2446.     Inc(tmp);
  2447.     tmpSt:=TeeMsg_DefaultFunctionName+IntToStr(tmp);
  2448.   end;
  2449.   result:=tmpSt;
  2450. end;
  2451.  
  2452. Procedure AssignSeries(Var OldSeries,NewSeries:TChartSeries);
  2453. Var OldName   : String;
  2454.     newPos    : Longint;
  2455.     tmpPos    : Longint;
  2456.     tmpSeries : TChartSeries;
  2457. begin
  2458.   NewSeries.Assign(OldSeries);
  2459.   With NewSeries do
  2460.   begin    { events }
  2461.     AfterDrawValues  :=OldSeries.AfterDrawValues;
  2462.     BeforeDrawValues :=OldSeries.BeforeDrawValues;
  2463.     OnAfterAdd       :=OldSeries.OnAfterAdd;
  2464.     OnBeforeAdd      :=OldSeries.OnBeforeAdd;
  2465.     OnClearValues    :=OldSeries.OnClearValues;
  2466.     OnClick          :=OldSeries.OnClick;
  2467.     OnDblClick       :=OldSeries.OnDblClick;
  2468.     OnGetMarkText    :=OldSeries.OnGetMarkText;
  2469.   end;
  2470.   OldName:=OldSeries.Name;
  2471.  
  2472.   While OldSeries.LinkedSeries.Count>0 do
  2473.   begin
  2474.     tmpSeries:=TChartSeries(OldSeries.LinkedSeries[0]);
  2475.     { after removing... }
  2476.     With tmpSeries.DataSources do
  2477.     begin
  2478.       if IndexOf(NewSeries)=-1 then Add(NewSeries);
  2479.       if IndexOf(OldSeries)<>-1 then Remove(OldSeries);
  2480.     end;
  2481.     NewSeries.AddLinkedSeries(tmpSeries);
  2482.     OldSeries.RemoveLinkedSeries(tmpSeries);
  2483.   end;
  2484.  
  2485.   { Swap Series on Chart list }
  2486.   With OldSeries.ParentChart.SeriesList do
  2487.   begin
  2488.     tmpPos:=IndexOf(OldSeries);
  2489.     newPos:=IndexOf(NewSeries);
  2490.     Exchange(tmpPos,newPos);
  2491.   end;
  2492.  
  2493.   OldSeries.Free;
  2494.   OldSeries:=nil;
  2495.   With NewSeries do
  2496.   begin
  2497.     Name:=OldName;
  2498.     if ( DataSource=nil ) and ( csDesigning in ComponentState ) then
  2499.     FillSampleValues(NumSampleValues);
  2500.     RefreshSeries;
  2501.   end;
  2502. end;
  2503.  
  2504. Function CreateNewTeeFunction(ASeries:TChartSeries; AClass:TTeeFunctionClass):TTeeFunction;
  2505. begin
  2506.   result:=AClass.Create(ASeries.Owner);
  2507.   result.ParentSeries:=ASeries;
  2508.   result.Name:=GetNewFunctionName(ASeries.Owner);
  2509. end;
  2510.  
  2511. Function CreateNewSeries( AOwner:TComponent;
  2512.               AChart:TCustomAxisPanel;
  2513.               AClass:TChartSeriesClass;
  2514.               AFunctionClass:TTeeFunctionClass):TChartSeries;
  2515. begin
  2516.   if AOwner=nil then AOwner:=AChart;  { 4.0 }
  2517.   result:=AClass.Create(AOwner);
  2518.   result.ParentChart:=AChart;
  2519.   result.Name:=GetNewSeriesName(AOwner);
  2520.   if AFunctionClass<>nil then CreateNewTeeFunction(result,AFunctionClass);
  2521. end;
  2522.  
  2523. Function CloneChartSeries(ASeries:TChartSeries):TChartSeries;
  2524. Var tmp : TTeeFunctionClass;
  2525. begin
  2526.   With ASeries do
  2527.   begin
  2528.     if FunctionType=nil then tmp:=nil
  2529.             else tmp:=TTeeFunctionClass(FunctionType.ClassType);
  2530.     result:=CreateNewSeries(Owner,ParentChart,TChartSeriesClass(ClassType),tmp);
  2531.   end;
  2532.   result.Assign(ASeries);
  2533.   { add values from ASeries --> result }
  2534.   { if DataSource is not nil, values are already added in Assign }
  2535.   if result.DataSource=nil then result.AssignValues(ASeries);
  2536. end;
  2537.  
  2538. procedure ChangeSeriesType(Var ASeries:TChartSeries; NewType:TChartSeriesClass);
  2539. var NewSeries : TChartSeries;
  2540. begin
  2541.   if ASeries.ClassType<>NewType then { only if different classes }
  2542.   begin
  2543.     NewSeries:=CreateNewSeries(ASeries.Owner,ASeries.ParentChart,NewType,nil);
  2544.     if Assigned(newSeries) then
  2545.     begin
  2546.       AssignSeries(ASeries,newSeries);
  2547.       ASeries:=NewSeries;  { <-- change parameter }
  2548.     end;
  2549.   end;
  2550. end;
  2551.  
  2552. procedure ChangeAllSeriesType( AChart:TCustomChart; AClass:TChartSeriesClass );
  2553. Var t         : Integer;
  2554.     tmpSeries : TChartSeries;
  2555. begin
  2556.   for t:=0 to AChart.SeriesCount-1 do
  2557.   begin
  2558.     tmpSeries:=AChart[t];
  2559.     ChangeSeriesType(tmpSeries,AClass);
  2560.   end;
  2561. end;
  2562.  
  2563. Function TTeeSeriesTypes.GetSeriesType(Index:Integer):TTeeSeriesType;
  2564. begin
  2565.   result:=TTeeSeriesType(Items[Index]);
  2566. end;
  2567.  
  2568. Procedure RegisterTeeSeriesFunction( ASeriesClass:TChartSeriesClass;
  2569.                      AFunctionClass:TTeeFunctionClass;
  2570.                      Const ADescription,AGalleryPage:String;
  2571.                      ANumGallerySeries : Integer );
  2572. var t             : Longint;
  2573.     NewSeriesType : TTeeSeriesType;
  2574. begin
  2575.   if Assigned(ASeriesClass) then Classes.RegisterClass(ASeriesClass);
  2576.   if Assigned(AFunctionClass) then Classes.RegisterClass(AFunctionClass);
  2577.   if not Assigned(TeeSeriesTypes) then TeeSeriesTypes:=TTeeSeriesTypes.Create;
  2578.   With TeeSeriesTypes do
  2579.   for t:=0 to Count-1 do
  2580.   With SeriesType[t] do
  2581.     if (SeriesClass=ASeriesClass) and
  2582.        (FunctionClass=AFunctionClass) then Exit;
  2583.   NewSeriesType:=TTeeSeriesType.Create;
  2584.   with NewSeriesType do
  2585.   begin
  2586.     SeriesClass   := ASeriesClass;
  2587.     FunctionClass := AFunctionClass;
  2588.     Description   := ADescription;
  2589.     GalleryPage   := AGalleryPage;
  2590.     NumGallerySeries := ANumGallerySeries;
  2591.   end;
  2592.   TeeSeriesTypes.Add(NewSeriesType);
  2593. end;
  2594.  
  2595. { Adds a new Series component definition for the Gallery }
  2596. Procedure RegisterTeeSeries( ASeriesClass:TChartSeriesClass;
  2597.                  Const ADescription,AGalleryPage:String;
  2598.                  ANumGallerySeries : Integer );
  2599. begin
  2600.   RegisterTeeSeriesFunction( ASeriesClass,
  2601.                  nil,
  2602.                  ADescription,
  2603.                  AGalleryPage,
  2604.                  ANumGallerySeries );
  2605. end;
  2606.  
  2607. Procedure RegisterTeeFunction( AFunctionClass:TTeeFunctionClass;
  2608.                    Const ADescription,AGalleryPage:String;
  2609.                    ANumGallerySeries : Integer );
  2610. begin
  2611.   RegisterTeeSeriesFunction( nil,
  2612.                  AFunctionClass,
  2613.                  ADescription,
  2614.                  AGalleryPage,
  2615.                  ANumGallerySeries);
  2616. end;
  2617.  
  2618. Procedure RegisterTeeBasicFunction( AFunctionClass:TTeeFunctionClass;
  2619.                     Const ADescription:String );
  2620. begin
  2621.   RegisterTeeFunction( AFunctionClass,
  2622.                ADescription,
  2623.                TeeMsg_GalleryFunctions,2);
  2624. end;
  2625.  
  2626. Function GetTeeFunctionDescription( AFunctionClass:TTeeFunctionClass):String;
  2627. var t : Longint;
  2628. begin
  2629.   result:='';
  2630.   With TeeSeriesTypes do
  2631.   for t:=0 to Count-1 do
  2632.   With SeriesType[t] do
  2633.   if FunctionClass=AFunctionClass then
  2634.   begin
  2635.     result:=Description;
  2636.     Exit;
  2637.   end;
  2638. end;
  2639.  
  2640. Procedure InternalUnRegister(IsSeries:Boolean; AClass:TComponentClass);
  2641. var tmp : TTeeSeriesType;
  2642.     t   : Longint;
  2643. begin
  2644.   if Assigned(TeeSeriesTypes) then
  2645.   begin
  2646.     t:=0;
  2647.     While t<TeeSeriesTypes.Count do
  2648.     begin
  2649.       tmp:=TeeSeriesTypes[t];
  2650.       if (IsSeries and (tmp.SeriesClass=AClass)) or
  2651.        ((not IsSeries) and (tmp.FunctionClass=AClass)) then
  2652.       begin
  2653.     tmp.Free;
  2654.     TeeSeriesTypes.Delete(t);
  2655.       end
  2656.       else Inc(t);
  2657.     end;
  2658.   end;
  2659. end;
  2660.  
  2661. Procedure UnRegisterTeeSeries(Const ASeriesList:Array of TChartSeriesClass);
  2662. var t : Integer;
  2663. begin
  2664.   for t:=Low(ASeriesList) to High(ASeriesList) do
  2665.       InternalUnRegister(True,ASeriesList[t]);
  2666. end;
  2667.  
  2668. Procedure UnRegisterTeeFunctions(Const AFunctionList:Array of TTeeFunctionClass);
  2669. var t : Integer;
  2670. begin
  2671.   for t:=Low(AFunctionList) to High(AFunctionList) do
  2672.       InternalUnRegister(False,AFunctionList[t]);
  2673. end;
  2674.  
  2675. Procedure TeeGalleryExitProc; far;
  2676. var t : Integer;
  2677. begin
  2678.   With TeeSeriesTypes do
  2679.   for t:=0 to Count-1 do SeriesType[t].Free;
  2680.   TeeSeriesTypes.Free;
  2681.   TeeSeriesTypes:=nil;
  2682. end;
  2683.  
  2684. {$IFNDEF D1}
  2685.  
  2686. { TTeeDragObject }
  2687. constructor TTeeDragObject.Create(Const APart: TChartClickedPart);
  2688. begin
  2689.   FPart:=APart;
  2690. end;
  2691.  
  2692. {function TTeeDragObject.GetDragImages: TCustomImageList;
  2693. begin
  2694.   Result := FPart.GetDragImages;
  2695. end;}
  2696.  
  2697. {procedure TTeeDragObject.HideDragImage;
  2698. begin
  2699.   if FPart.GetDragImages <> nil then
  2700.     FPart.GetDragImages.HideDragImage;
  2701. end;
  2702.  
  2703. procedure TTeeDragObject.ShowDragImage;
  2704. begin
  2705.   if FPart.GetDragImages <> nil then
  2706.     FPart.GetDragImages.ShowDragImage;
  2707. end;
  2708. }
  2709. const crTeeDrag=2021;
  2710.       TeeMsg_TeeDrag = 'crTeeDrag'; { string cursor name (dont translate) }
  2711.  
  2712. function TTeeDragObject.GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor;
  2713. begin
  2714.   if Accepted then
  2715.     Result := crTeeHand
  2716.   else
  2717.     Result := crNoDrop;
  2718. end;
  2719.  
  2720. procedure TTeeDragObject.Finished(Target: TObject; X, Y: Integer; Accepted: Boolean);
  2721. begin
  2722.   if not Accepted then
  2723.   begin
  2724. {    FPart.DragCanceled;}
  2725. {    Target := nil;}
  2726.   end;
  2727. {  if Assigned(FPart. FOnEndDrag) then FOnEndDrag(Self, Target, X, Y);}
  2728. {  FPart.DoEndDrag(Target, X, Y);}
  2729. end;
  2730. {$ENDIF}
  2731.  
  2732. initialization
  2733.   TeeSeriesTypes      :=nil;     { List of available Series/Function types }
  2734.   AnimatedZoomFactor  :=3.0;     { controls the animated zoom "speed" }
  2735.   TeeZoomMouseButton  :=mbLeft;  { button used to zoom }
  2736.   TeeScrollMouseButton:=mbRight; { button used to scroll }
  2737.   TeeZoomKeyShift     :=[];      { keys that should be pressed to start zoom }
  2738.   TeeScrollKeyShift   :=[];      { keys that should be pressed to start scrolltmo }
  2739.   RegisterClasses([ TChartLegend,TChartGradient,TChartWall,TChartTitle ]);
  2740.   RegisterTeeBasicFunction( TAddTeeFunction,      TeeMsg_FunctionAdd );
  2741.   RegisterTeeBasicFunction( TSubtractTeeFunction, TeeMsg_FunctionSubtract );
  2742.   RegisterTeeBasicFunction( TMultiplyTeeFunction, TeeMsg_FunctionMultiply );
  2743.   RegisterTeeBasicFunction( TDivideTeeFunction,   TeeMsg_FunctionDivide );
  2744.   RegisterTeeBasicFunction( THighTeeFunction,     TeeMsg_FunctionHigh );
  2745.   RegisterTeeBasicFunction( TLowTeeFunction,      TeeMsg_FunctionLow );
  2746.   RegisterTeeBasicFunction( TAverageTeeFunction,  TeeMsg_FunctionAverage );
  2747. {$IFDEF D1}
  2748.   AddExitProc(TeeGalleryExitProc);
  2749. {$ELSE}
  2750. finalization
  2751.   TeeGalleryExitProc;
  2752. {$ENDIF}
  2753. end.
  2754.